UnauthorizedAccessException cannot resolve Directory.GetFiles failure

Viewed 37526

Directory.GetFiles method fails on the first encounter with a folder it has no access rights to.

The method throws an UnauthorizedAccessException (which can be caught) but by the time this is done, the method has already failed/terminated.

The code I am using is listed below:

try
{
    // looks in stated directory and returns the path of all files found                
    getFiles = Directory.GetFiles(
        @directoryToSearch, 
        filetype, 
        SearchOption.AllDirectories);             
}
catch (UnauthorizedAccessException) 
{ 
}

As far as I am aware, there is no way to check beforehand whether a certain folder has access rights defined.

In my example, I'm searching on a disk across a network and when I come across a root access only folder, my program fails.

6 Answers

.Net 4's Directory.EnumerateFiles does work, but you've got to be careful how you evaluate the enumerable and do that part inside the try-catch block. The biggest issue is making sure you don't stop processing at the first exception (which I think answer https://stackoverflow.com/a/1393219/89584 above has this problem, please correct me if I'm wrong there).

The following works and gives you an Enumerable so you don't have to evaluate the entire file tree if you're looking for the first match, etc.

private IEnumerable<String> FindAccessableFiles(string path, string file_pattern, bool recurse)
{
  IEnumerable<String> emptyList = new string[0];

  if (File.Exists(path))
    return new string[] { path };

  if (!Directory.Exists(path))
    return emptyList;

  var top_directory = new DirectoryInfo(path);

  // Enumerate the files just in the top directory.
  var files = top_directory.EnumerateFiles(file_pattern);
  var filesLength = files.Count();
  var filesList = Enumerable
            .Range(0, filesLength)
            .Select(i =>
            {
              string filename = null;
              try
              {
                var file = files.ElementAt(i);
                filename = file.FullName;
              }
              catch (UnauthorizedAccessException)
              {
              }
              catch (InvalidOperationException)
              {
                    // ran out of entries
              }
              return filename;
            })
            .Where(i => null != i);

        if (!recurse)
          return filesList;

        var dirs = top_directory.EnumerateDirectories("*");
        var dirsLength = dirs.Count();
        var dirsList = Enumerable
            .Range(0, dirsLength)
            .SelectMany(i =>
            {
              string dirname = null;
              try
              {
                var dir = dirs.ElementAt(i);
                dirname = dir.FullName;
                return FindAccessableFiles(dirname, file_pattern, required_extension, recurse);
              }
              catch (UnauthorizedAccessException)
              {
              }
              catch (InvalidOperationException)
              {
                 // ran out of entries
              }

              return emptyList;
            })

  return Enumerable.Concat(filesList, dirsList);
}

improvements to the above welcome.

Related