There is no effective way for you to handle this case. If the iterator itself is throwing an exception when trying to get the next item then it is not going to be in a position to give you the item after that; it is no longer in a "valid" state. Once an exception is thrown you're done with that iterator.
Your only option here is to not query the entire drive using this method. Perhaps you could write your own iterator to traverse the drive manually in such a way that items that cannot be traversed are skipped more gracefully.
So, to do this manual traversal. We can start out with a generalize Traverse
method that can traverse any tree (non-recursively, to better handle deep stacks efficiently):
public static IEnumerable<T> Traverse<T>(
this IEnumerable<T> source
, Func<T, IEnumerable<T>> childrenSelector)
{
var stack = new Stack<T>(source);
while (stack.Any())
{
var next = stack.Pop();
yield return next;
foreach (var child in childrenSelector(next))
stack.Push(child);
}
}
Now we just grab the root, traverse it, and use a method of getting the sub directories that won't throw an exception:
var root = new DirectoryInfo("C:\\");
var allFiles = new[] { root }.Traverse(dir => GetDirectoriesWithoutThrowing(dir))
.SelectMany(dir => GetFilesWithoutThrowing(dir));
The method to get the sub directories can start out as something like this, but may need to be fleshed out:
private static IEnumerable<DirectoryInfo> GetDirectoriesWithoutThrowing(
DirectoryInfo dir)
{
try
{
return dir.GetDirectories();
}
catch (Exception)//if possible catch a more derived exception
{
//TODO consider logging the exception
return Enumerable.Empty<DirectoryInfo>();
}
}
Note that you can play around with this particular part a bit. You may be able to get some of the sub directories out here even if you can't get others, you'll likely need to adjust the error handling, etc. The get files version will be essentially the same, but just with GetFiles
instead.