UnauthorizedAccessException cannot resolve Directory.GetFiles failure

The Directory.GetFiles method fails when it first encounters a folder in which it does not have permissions.

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

The code I'm using is 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 know, there is no way to check in advance whether a certain folder has certain access rights.

In my example, I search the disk over the network, and when I encounter a root folder for access only, my program crashes.

+22
c # exception-handling unauthorized
Sep 08 '09 at 10:23
source share
7 answers

To gain control over the level you want, you should probably examine one directory at a time, rather than a whole tree. The following method fills the given IList<string> all the files found in the directory tree, except for those where the user does not have access:

 // using System.Linq private static void AddFiles(string path, IList<string> files) { try { Directory.GetFiles(path) .ToList() .ForEach(s => files.Add(s)); Directory.GetDirectories(path) .ToList() .ForEach(s => AddFiles(s, files)); } catch (UnauthorizedAccessException ex) { // ok, so we are not allowed to dig into that directory. Move on. } } 
+17
Sep 08 '09 at 10:32
source share

.Net 4 Directory.EnumerateFiles works, but you have to be careful how you evaluate the enumerated amount and execute this part inside the try-catch block. The biggest problem is to make sure you don't stop processing in the first exception (which seems to me the answer is https://stackoverflow.com/questions/90626/ ... above, please correct me if I'm wrong there).

The following steps give you Enumerable, so you donโ€™t need to evaluate the entire file tree if you are 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 in greeting.

+4
Mar 22 2018-12-22T00:
source share

This is an improvement on Malcolm's answer (http://stackoverflow.com/a/9831340/226181). This scans all logical drives for the file match pattern and ignores inaccessible directories.

  static List<string> SearchFiles(string pattern) { var result = new List<string>(); foreach (string drive in Directory.GetLogicalDrives()) { Console.WriteLine("searching " + drive); var files = FindAccessableFiles(drive, pattern, true); Console.WriteLine(files.Count().ToString() + " files found."); result.AddRange(files); } return result; } private static IEnumerable<String> FindAccessableFiles(string path, string file_pattern, bool recurse) { Console.WriteLine(path); var list = new List<string>(); var required_extension = "mp4"; if (File.Exists(path)) { yield return path; yield break; } if (!Directory.Exists(path)) { yield break; } if (null == file_pattern) file_pattern = "*." + required_extension; var top_directory = new DirectoryInfo(path); // Enumerate the files just in the top directory. IEnumerator<FileInfo> files; try { files = top_directory.EnumerateFiles(file_pattern).GetEnumerator(); } catch (Exception ex) { files = null; } while (true) { FileInfo file = null; try { if (files != null && files.MoveNext()) file = files.Current; else break; } catch (UnauthorizedAccessException) { continue; } catch (PathTooLongException) { continue; } yield return file.FullName; } if (!recurse) yield break; IEnumerator<DirectoryInfo> dirs; try { dirs = top_directory.EnumerateDirectories("*").GetEnumerator(); } catch (Exception ex) { dirs = null; } while (true) { DirectoryInfo dir = null; try { if (dirs != null && dirs.MoveNext()) dir = dirs.Current; else break; } catch (UnauthorizedAccessException) { continue; } catch (PathTooLongException) { continue; } foreach (var subpath in FindAccessableFiles(dir.FullName, file_pattern, recurse)) yield return subpath; } } 
+4
May 26 '12 at 03:17
source share

I know this thread is outdated, but if someone came across this and needs an answer, I found a recursive solution here:

 public static List<string> GetAllAccessibleFiles(string rootPath, List<string> alreadyFound = null) { if (alreadyFound == null) alreadyFound = new List<string>(); DirectoryInfo di = new DirectoryInfo(rootPath); var dirs = di.EnumerateDirectories(); foreach (DirectoryInfo dir in dirs) { if (!((dir.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)) { alreadyFound = GetAllAccessibleFiles(dir.FullName, alreadyFound); } } var files = Directory.GetFiles(rootPath); foreach (string s in files) { alreadyFound.Add(s); } return alreadyFound; } 

It returns a List<string> containing the full path to all files located in accessible directories below the specified root directory. Call it that:

 var files = GetAllAccessibleFiles(@"C:\myDirectory"); 

So one result could be like this:

 C:\myDirectory\a\a.txt C:\myDirectory\a\b.mp3 C:\myDirectory\b\a\a\foo.txt C:\myDirectory\b\b\b\hello.exe C:\myDirectory\b\c\bar.jpg C:\myDirectory\and\so\on.bar C:\myDirectory\a_file_in_root.bmp 

Hope this helps someone!

+4
Dec 22 '13 at 19:34
source share

In .NET 4, this becomes much simpler, see http://msdn.microsoft.com/en-us/library/dd997370.aspx

+3
Apr 18 '10 at 20:10
source share
 public string[] GetFilesFrom(string dir, string search_pattern, bool recursive) { List<string> files = new List<string>(); string[] temp_files = new string[0]; try { temp_files = Directory.GetFiles(dir, search_pattern, SearchOption.TopDirectoryOnly); } catch { } files.AddRange(temp_files); if (recursive) { string[] temp_dirs = new string[0]; try { temp_dirs = Directory.GetDirectories(dir, search_pattern, SearchOption.TopDirectoryOnly); } catch { } for (int i = 0; i < temp_dirs.Length; i++) files.AddRange(GetFilesFrom(temp_dirs[i], search_pattern, recursive)); } return files.ToArray(); } 

This is my solution for this problem. Simple and reliable.

+1
Oct 06 '14 at 17:27
source share

The simplest version:

 IEnumerable<String> GetAllFiles(string path, string searchPattern) { return System.IO.Directory.EnumerateFiles(path, searchPattern).Union( System.IO.Directory.EnumerateDirectories(path).SelectMany(d => { try { return GetAllFiles(d, searchPattern); } catch (UnauthorizedAccessException e) { return Enumerable.Empty<String>(); } })); } 
0
Feb 19 '15 at 16:41
source share



All Articles