UnauthorizedAccessException无法parsingDirectory.GetFiles失败

Directory.GetFiles方法在第一次遇到一个没有访问权限的文件夹时失败。

该方法抛出一个UnauthorizedAccessException(可以被捕获),但到这个时候,该方法已经失败/终止。

我使用的代码如下所示:

try { // looks in stated directory and returns the path of all files found getFiles = Directory.GetFiles( @directoryToSearch, filetype, SearchOption.AllDirectories); } catch (UnauthorizedAccessException) { } 

据我所知,没有办法事先检查某个文件夹是否有访问权限定义。

在我的示例中,我通过networking在磁盘上search,当我遇到仅限根访问权限的文件夹时,我的程序失败。

为了获得所需级别的控制权,您应该一次探测一个目录,而不是整棵树。 以下方法使用目录树中的所有文件填充给定的IList<string> ,除了那些用户无权访问的文件外:

 // 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. } } 

这是对Malcolm答案的一个增强(http://stackoverflow.com/a/9831340/226181)。; 这将扫描所有逻辑驱动器的文件匹配模式,并忽略不可访问的目录。

  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; } } 

.net 4的Directory.EnumerateFiles可以工作,但是你必须小心如何评估enumerable,并在try-catch块内部执行该部分。 最大的问题是确保你不停止处理的第一个exception(我认为上述答案https://stackoverflow.com/a/1393219/89584有这个问题,请纠正我,如果我错了)。;

下面的工作,并给你一个Enumerable,所以你不必评估整个文件树,如果你正在寻找第一场比赛等。

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

以上的欢迎改进。

我知道这个线程是旧的,但万一有人绊倒在这,需要一个答案,我有一个recursion的解决scheme在这里:

 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; } 

它返回一个List<string>其中包含指定根目录下的可访问目录中所有文件的完整path。 像这样调用它:

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

所以一个结果可能是这样的:

 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 

希望它可以帮助别人!

在.NET 4中,这变得更容易,请参阅http://msdn.microsoft.com/en-us/library/dd997370.aspx

 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(); } 

这是我解决这个问题的方法。 简单和失败的安全。

最简单的版本:

 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>(); } })); } 
Interesting Posts