Click here to Skip to main content
15,887,414 members
Articles / Productivity Apps and Services / Microsoft Office / Microsoft Access
Tip/Trick

Enumerate File System Getting Past UnauthorizedAccessExceptions

Rate me:
Please Sign up or sign in to vote.
4.86/5 (3 votes)
21 Jul 2014CPOL2 min read 10.9K   155   9  
Search for files and folders and don't exit the search when there is an error accessing a protected folder, just skip it.

Introduction

The standard .NET file access API raises an UnauthorizedAccessException when recursively traversing the file system, making it difficult to enumerate large directory structures. Microsoft notes that this is by design (Directory.EnumerateDirectory etc. unusable due to frequent UnauthorizedAccessExceptions (even runas Administrator)[^]), but most developers would likely prefer it to function more like good old fashioned DOS's "DIR /A/S/B". This code functions similar to the latter.

Background

This code was originally written by BlueMonkMN for the String file and directory enumerators (stackoverflow[^]), which work great. The code posted here extends that idea to use the FileSystemInfo enumerators to get more file details. If you only need string details, use the original code. If you need full file details, use this code.

Using the Code

Review the attached test cases for more detailed usage, but basic usage is similar to the standard .NET API:

C#
var dir = new DirectoryInfo(@"C:\MyFolder");
var sfe = new SafeFileEnumerator(dir, "*", SearchOption.AllDirectories);
foreach (var fsi in sfe){
    if (fsi is FileInfo){
        var fi = fsi as FileInfo;
        Debug.Write(String.Format("File: {0}: {1}", fi.Name, fi.Length));
    } else if (fsi is DirectoryInfo){
        Debug.Write(String.Format("Folder: {0}", fsi.FullName));
    }
}

As tested out in the UnitTests, this example explains what is accomplished by this code. When recursively scanning the root folder "UnitTest1", we should return all folders except "Sub4", and all files except files in folders "Sub3" and "Sub4". The key difference between this code and the stock .NET code is that the stock code will not return folders "Sub6" and "Sub8".

UnitTest1
  Sub1
  Sub2
    Sub5
    Sub7
  Sub3 <-- Denied Access
    Sub4
  Sub6
    Sub8

Points of Interest

There are some differences between this code and the original String version of the code, including:

  1. Checks for UnauthorizedAccessExceptions on the root folder.
  2. Has Abort() function that is handy for canceling large background searches.
  3. Cleanup moved to private Dispose() function to centralize how cleanups are done.

The key part of the code, recursively creating two enumerators for each directory structure so you know where to continue from an error, is logically identical to the original code. The most noteworthy part is the MoveNext() function.

C#
public bool MoveNext(){
    // Enumerate the files in the current folder

    try
    {
        if ((fileEnumerator != null) && (fileEnumerator.MoveNext()))
            return true;
    } 
    catch (PathTooLongException){}
 
    // Move to the next directory
    while ((directoryEnumerator != null) && (directoryEnumerator.MoveNext())) {
        Dispose(true, false);
 
        try {
            fileEnumerator = new SafeFileEnumerator(
                directoryEnumerator.Current,
                pattern,
                SearchOption.AllDirectories,
                errors
            ).GetEnumerator();
        } catch (Exception ex){
            // If we get an error in the folder, skip it (this is the magic part)...
            errors.Add(ex);
            // ... and continue with the next folder.
            continue;
        }
 
        // Open up the current folder file enumerator
        if (fileEnumerator.MoveNext())
            return true;
    } // End While

    Dispose(true, true);
    return false;
}

History

  • 11th December, 2013: Initial public draft
  • 20th July 2014: Added some additional catch blocks to check for PathTooLong exceptions.  Encapsulated the "Smother Errors" routine in to a single function, so you can update to do something other than just print to Debug Output.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --