6

In .NET 4, there's this Directory.EnumerateFiles() method with recursion that seems handy.
However, if an Exception occurs within a recursion, how can I continue/recover from that and continuing enumerate the rest of the files?

try
{
  var files = from file in Directory.EnumerateFiles("c:\\",
                           "*.*", SearchOption.AllDirectories)
              select new
              {
                File = file
              };

  Console.WriteLine(files.Count().ToString());

}
catch (UnauthorizedAccessException uEx)
{
  Console.WriteLine(uEx.Message);
}
catch (PathTooLongException ptlEx)
{
  Console.WriteLine(ptlEx.Message);
}
Magnus Johansson
  • 28,010
  • 19
  • 106
  • 164
  • 1
    You could probably write your own version in a few lines with extra error recovery that you require. – leppie Apr 01 '10 at 10:21

4 Answers4

3

I did found a solution to this. By using a stack to push the enumeration results, one can indeed handle the exceptions. Here's a code snippet: (inspired by this article)

List<string> results = new List<string>();
string start = "c:\\";
results.Add(start);
Stack<string> stack = new Stack<string>();

do
{
  try
  {
    var dirs = from dir in Directory.EnumerateDirectories(
                     start, "*.*", SearchOption.TopDirectoryOnly)
                select dir;

    Array.ForEach(dirs.ToArray(), stack.Push);
    start = stack.Pop();
    results.Add(start);
  }
  catch (UnauthorizedAccessException ex)
  {
    Console.WriteLine(ex.Message);
    start = stack.Pop();
    results.Add(start);
  }

} while (stack.Count != 0);

foreach (string file in results)
{
  Console.WriteLine(file);
}
Magnus Johansson
  • 28,010
  • 19
  • 106
  • 164
  • 1
    You don't need the LINQ that does nothing - replace `var dirs = from dir in Directory.EnumerateDirectories( start, "*.*", SearchOption.TopDirectoryOnly) select dir;` with `var dirs = Directory.EnumerateDirectories(start, "*.*", SearchOption.TopDirectoryOnly);` – NetMage Oct 20 '17 at 22:57
  • You also don't need to use the `TopDirectoryOnly` version - just use `Directory.EnumerateDirectories(start)`. – NetMage Oct 21 '17 at 00:22
1

I had the same problem and re-implemented the functionality. You can find the solution at http://rwtools.codeplex.com/.

Inside are classes like "DirectoryEnumerator" and "FileEnumerator" which ignores errors, or (if sombody likes) throws the error and continue iterating.

Hope it helps.

Regards, Sandro

RinderWahn
  • 11
  • 1
0

I think that this approach does not work correctly. Although the UnauthorizedAccessException is caught, the iteration immediately stops when it occurs. So you just get all files that were retrieved before the exception was thrown.

  • 1
    Jürgen, that is exactly my question. In a situation where I want all files, an Exception should be ignored, so I can enumerate all the files. – Magnus Johansson May 30 '10 at 11:01
-2

The call to Directory.EnumerateFiles(..) will only set-up the enumerator, because of lazy-evaluation. It's when you execute it, using a foreach that you can raise the exception.

So you need to make sure that the exception is handled at the right place so that the enumeration can continue.

var files = from file in Directory.EnumerateFiles("c:\\",
                           "*.*", SearchOption.AllDirectories)
              select new
              {
                File = file
              };

foreach (var file in files)
{
    try
    {          
        Console.Writeline(file);
    }
    catch (UnauthorizedAccessException uEx)
    {
        Console.WriteLine(uEx.Message);
    }
    catch (PathTooLongException ptlEx)
    {
        Console.WriteLine(ptlEx.Message);
    }
}

Update: There's some extra info in this question

Community
  • 1
  • 1
Matt Warren
  • 10,279
  • 7
  • 48
  • 63
  • 3
    I dont think this works. file is bound before the try/catch, and hence the exception with be thrown outside your try/catch. – leppie Apr 01 '10 at 10:20