Jeff Prosise's Blog

Silverlight 4's New Local File System Support

In my last blog post, I wrote about Silverlight 4 applications that run outside the browser with elevated permissions and their ability to leverage COM automation servers on the host PC. Another privilege that applications with elevated permissions—also known as "trusted apps"—enjoy is the ability to access parts of the local file system without prompting the user with an OpenFileDialog or SaveFileDialog. This feature opens the door to types of applications that simply weren't possible with Silverlight 3.

File access is limited to certain locations on the hard disk: primarily the "My" folders such as My Documents, My Pictures, and My Music. But within those constraints, file system access works pretty much the same in Silverlight as it does in .NET. You generally begin by calling Environment.GetFolderPath to acquire a path to the folder you wish to access. The following code snippet enumerates the files in My Documents and stuffs the file names into a ListBox named FileList:

string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

 

foreach (string file in Directory.EnumerateFiles(path))

{

    FileList.Items.Add(file.Substring(file.LastIndexOf('\\') + 1));

}

Of course, you're not limited to enumerating files. You can open files, create files, and delete files, and you can do the same with directories. Plus, there's no limit on the amount of data you can write to the hard disk since the user okayed the elevated permissions when the application was installed.

To demonstrate Silverlight file access in action, I wrote the My Pictures Viewer pictured below. When started, it populates a TreeView control with all the folders and subfolders in your My Pictures directory. You can expand and collapse branches of the tree, and when you select a folder, the right half of the window is populated with thumbnail images of all the PNGs and JPGs in that directory. You can then click a thumbnail to see a close-up of the picture in a child window. Click the picture (or the X in the child window's upper right corner) to close the child window and continue photo browsing.

My Pictures Viewer 

You can download the source code and try it for yourself. Run the application once in your browser and right-click it to install it as an out-of-browser application. Once the viewer is running outside the browser, you can begin browsing pictures.

The code to populate the TreeView with folder names looks like this:

if (Application.Current.HasElevatedPermissions)

{

    string path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);

 

    foreach (string dir in Directory.EnumerateDirectories(path))

    {

        TreeViewItem item = new TreeViewItem();

        item.Header = dir.Substring(dir.LastIndexOf('\\') + 1);

        DirectoryTree.Items.Add(item);

        ProcessFolder(dir, item.Items);

    }

} 

ProcessFolder is a recursive method that's implemented this way:

private void ProcessFolder(string path, ItemCollection items)

{

    foreach (string dir in Directory.EnumerateDirectories(path))

    {

        TreeViewItem item = new TreeViewItem();

        item.Header = dir.Substring(dir.LastIndexOf('\\') + 1);

        items.Add(item);

        ProcessFolder(dir, item.Items);

    }

} 

Perhaps the most interesting part of the source code is how it generates thumbnail images. It uses a BitmapImage to decode each image file. Then it assigns the BitmapImage to an Image object, uses WriteableBitmap.Render with a ScaleTransform to generate a thumbnail, and then, strangely enough, makes a copy of the WriteableBitmap in another WriteableBitmap. The second WriteableBitmap is the one that's ultimately assigned to an Image object to display the thumbnail on the screen.

At first glance, this may appear gratuitous. Why not just assign the BitmapImage created from the image file directly to the Image that displays the thumbnail on the screen? Furthermore, why go to the trouble of making a copy of the WriteableBitmap? The short answer is that I did it this way to avoid out-of-memory exceptions, which are all too common in Silverlight applications that display digital photos. In fact, I'm planning a follow-up blog post that covers this in detail. Stay tuned.

On Dec 16 2009 9:56 AMBy jprosise With 11 Comments

Comments (11)

  1. Hey,

    Just wondering if you figured out a workaround for when the recursive call hits a directory that it does not have access to. It's preventing the tree to be properly populated. I am rooting the path to my documents, but apparently some of my subfolders are being denied. Thanks for any help

    Goody

  2. Hi, can you update this post to let us know if you can:

    1. Drag FROM the filesystem TO SL4 app (either in or out of browser)
    2. If so, can this be done CROSS PLATFORM?

    I need a SL4 app that can drag files from it to either a Windows filesystem or Mac filesystem.

    Help :-)

  3. What is the point of restricting file access to the special folders, when you can create a Scripting.FileSystemObject through automation and then access any file everywhere? I must be missing something.

  4. Hi,

    I need to access folder structure (ex:MyPictures) in web browser. Is it possible? if yes can any one tell me how to do?

    Thanks in advance

Leave a Comment