views:

165

answers:

3

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);
}
A: 

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

Matt Warren
I dont think this works. file is bound before the try/catch, and hence the exception with be thrown outside your try/catch.
leppie
A: 

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.

Jürgen Bayer
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
+1  A: 

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