UnauthorizedAccessException无法解析Directory.GetFiles失败

Ric*_*Ric 22 c# exception-handling getfiles unauthorized

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) 
{ 
}
Run Code Online (Sandbox Code Playgroud)

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

在我的示例中,我正在通过网络搜索磁盘,当我遇到仅限root访问权限的文件夹时,我的程序失败了.

Fre*_*örk 19

为了获得所需级别的控制权,您应该一次探测一个目录,而不是整个树.以下方法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.
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这将无法包含所有目录/文件,因为在第一个无法访问的文件/目录上抛出异常,并且在此之后您永远不会获得任何剩余的可访问文件. (17认同)
  • @Ric:`=>`是lambda运算符.你可以在这里阅读C#中的lambda表达式:http://msdn.microsoft.com/en-us/library/bb397687.aspx (3认同)

sch*_*dar 6

我知道这个帖子已经过时了,但万一有人偶然发现并需要一个答案,我在这里得到了一个递归解决方案:

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;
    }
Run Code Online (Sandbox Code Playgroud)

它返回一个List<string>包含给定根目录下可访问目录中所有文件的完整路径.像这样称呼它:

var files = GetAllAccessibleFiles(@"C:\myDirectory");
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

希望它可以帮到某人!

  • 如果您对文件夹的访问被拒绝,那么您的迭代器会抛出一个未处理的异常,并且您会丢失整个内容。 (3认同)

mat*_*rix 5

这是对 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)