Sometimes you need to enumerate the files in a folder and its subfolders and that can be a very long task, especially with large folders. This article will show a fast and easy way to enumerate all files in a folder when using UWP.

Enumerating files the traditional way

UWP runs in a sandbox and you don’t have access to all files in the system. One way to get access to a folder and its subfolders is to use the FolderPicker. You can’t access the folders directly (unless for some libraries when you ask for their use in the app manifest), and using the folder picker gives you access to other folders: you open it, the user selects a folder and you have access to it and its subfolders. That can be done with a code like this:

private static async Task<StorageFolder> SelectFolderAsync()
{
    var folderPicker = new Windows.Storage.Pickers.FolderPicker
    {
        SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop
    };
    folderPicker.FileTypeFilter.Add("*");
    StorageFolder folder = await folderPicker.PickSingleFolderAsync();
    return folder;
}

Once you get the folder reference, you can enumerate all files using a code like this:

private List<StorageFile> _allFiles;

private async Task GetFilesInFolder(StorageFolder folder)
{
    var items = await folder.GetItemsAsync();
    foreach (var item in items)
    {
        if (item is StorageFile)
            _allFiles.Add(item as StorageFile);
        else
            await GetFilesInFolder(item as StorageFolder);
    }
}

This recursive function will get all files and folders in the folder and will add the files to the files list and will call the function for all subfolders. Notice that you must use the StorageFolder and StorageFile classes to enumerate the files. While you can use .NET Standard 2.0 FileIO classes, this will be blocked by access permissions to UWP programs (for example, you will have access denied on the Documents library if you try to enumerate any file there with these classes even if you got the folder through the FolderPicker).

Using this function, I can get all files in a folder and fill a GridView in the main page with this function:

 

private async void GetFolderSlow(object sender, RoutedEventArgs e)
{
    StorageFolder folder = await SelectFolderAsync();
    if (folder != null)
    {
        DocsGrid.ItemsSource = null;
        StatusTxt.Text = "";
        var sw = new Stopwatch();
        sw.Start();
        _allFiles = new List<StorageFile>();
        await GetFilesInFolder(folder);
        DocsGrid.ItemsSource = _allFiles;
        sw.Stop();
        StatusTxt.Text = $"Ellapsed time: {sw.ElapsedMilliseconds}  {_allFiles.Count} files";
    }
}

In my machine, it takes about 2 minutes to enumerate the Documents Library (about 38,000 files). That is way more than using a .NET console program (in my machine, it took about 5 seconds to get all file names and process them to get their sizes), but there is no better way (until now – maybe there will be some kind of Full Thrust UWP app in the future :-)) to enumerate the files in UWP. Or there is?

Enumerating files the fast way

Yes, there is a faster way. You can use the Windows indexing service and query the files faster, when they are indexed. For that, you just need to create a QueryOptions instance and tell that you want to use the indexer. This code makes all the work:

 

private async void GetFolder(object sender, RoutedEventArgs e)
{
    var folder = await SelectFolderAsync();
    if (folder != null)
    {
        DocsGrid.ItemsSource = null;
        StatusTxt.Text = "";
        var sw = new Stopwatch();
        sw.Start();
        var queryOptions = new QueryOptions
        {
            FolderDepth = FolderDepth.Deep,
            IndexerOption = IndexerOption.UseIndexerWhenAvailable
        };
        var query = folder.CreateFileQueryWithOptions(queryOptions);
        var allFiles = await query.GetFilesAsync();
        DocsGrid.ItemsSource = allFiles;
        sw.Stop();
        StatusTxt.Text = $"Ellapsed time: {sw.ElapsedMilliseconds}  {allFiles.Count} files";
    }
}

As you can see, there is no need to have a recursive function. Setting the FolderDepth property to FolderDepth.Deep does all the recursive work for you. An you can use the index if it’s available and query for some files (like – only pictures or files created by an author). While this is not as fast as the console enumeration, it’s still twice as fast as the previous version.

Conclusions

Enumerating files in UWP is not very fast, but when you need it, you have a faster alternative to the default, using the indexer. That can be a handy alternative, especially when you need to filter the files.

All the source code for the article is in https://github.com/bsonnino/DocumentsAccess