There is a nice new method in .NET 4.0 for getting files in a directory in a streaming way via enumeration.
The problem here is that if one wishes to enumerate all files one may not know in advance which files or folders are access protected and can throw an UnauthorizedAccessException.
To reproduce, one can just run this fragment:
foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories)) { // whatever }
Before this .NET method existed it was possible to achieve roughly the same effect by implementing a recursive iterator on the string-array returning methods. But it's not quite as lazy as the new .NET method is.
So what to do? Can the UnauthorizedAccessException be suppressed or is a fact of life when using this method?
Seems to me that the method should have an overload accepting an action to deal with any exceptions.
To enumerate directories and files, use methods that return an enumerable collection of directory or file names, or their DirectoryInfo, FileInfo, or FileSystemInfo objects. If you want to search and return only the names of directories or files, use the enumeration methods of the Directory class.
File/parameter enumeration is a common technique used to search for suspicious files and parameter values in order to detect their existence or validity. Using this technique, it is possible to map additional parts of the application, which are not normally exposed to the public.
I Couldn't get the above to work, but here is my implementation, i've tested it on c:\users on a "Win7" box, because if has all these "nasty" dirs:
SafeWalk.EnumerateFiles(@"C:\users", "*.jpg", SearchOption.AllDirectories).Take(10)
Class:
public static class SafeWalk { public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt) { try { var dirFiles = Enumerable.Empty<string>(); if(searchOpt == SearchOption.AllDirectories) { dirFiles = Directory.EnumerateDirectories(path) .SelectMany(x => EnumerateFiles(x, searchPattern, searchOpt)); } return dirFiles.Concat(Directory.EnumerateFiles(path, searchPattern)); } catch(UnauthorizedAccessException ex) { return Enumerable.Empty<string>(); } } }
Ths issue with the above answer is that is does not take care of exception in sub directories. This would be a better way to handling those exceptions so you get ALL files from ALL subdirectories except those with threw an access exception:
/// <summary> /// A safe way to get all the files in a directory and sub directory without crashing on UnauthorizedException or PathTooLongException /// </summary> /// <param name="rootPath">Starting directory</param> /// <param name="patternMatch">Filename pattern match</param> /// <param name="searchOption">Search subdirectories or only top level directory for files</param> /// <returns>List of files</returns> public static IEnumerable<string> GetDirectoryFiles(string rootPath, string patternMatch, SearchOption searchOption) { var foundFiles = Enumerable.Empty<string>(); if (searchOption == SearchOption.AllDirectories) { try { IEnumerable<string> subDirs = Directory.EnumerateDirectories(rootPath); foreach (string dir in subDirs) { foundFiles = foundFiles.Concat(GetDirectoryFiles(dir, patternMatch, searchOption)); // Add files in subdirectories recursively to the list } } catch (UnauthorizedAccessException) { } catch (PathTooLongException) {} } try { foundFiles = foundFiles.Concat(Directory.EnumerateFiles(rootPath, patternMatch)); // Add files from the current directory } catch (UnauthorizedAccessException) { } return foundFiles; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With