UnauthorizedAccessException 无法解决 Directory.GetFiles 失败

发布于 2024-08-04 02:09:04 字数 613 浏览 8 评论 0原文

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

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

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

Directory.GetFiles method fails on the first encounter with a folder it has no access rights to.

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

The code I am using is listed 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 am aware, there is no way to check beforehand whether a certain folder has access rights defined.

In my example, I'm searching on a disk across a network and when I come across a root access only folder, my program fails.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不美如何 2024-08-11 02:09:04

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

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

In order to gain control on the level that you want, you should probably probe one directory at a time, instead of a whole tree. The following method populates the given IList<string> with all files found in the directory tree, except those where the user doesn't 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.
    }
}
抚你发端 2024-08-11 02:09:04

我知道这个线程已经很旧了,但是如果有人偶然发现这个问题并需要答案,我在这里得到了一个递归解决方案:

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 ,其中包含所有文件的完整路径给定根目录下的可访问目录。
这样称呼它:

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

希望它可以帮助某人!

I know this thread is old, but in case someone stumbles upon this and needs an answer, i got 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 an List<string> containing the full path to all files that are in accessible directories below the given root-directory.
Call it like this:

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 it helps someone!

梦里寻她 2024-08-11 02:09:04

这是对马尔科姆答案的增强(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;
        }
    }

This is an enhancement to Malcolm's answer (http://stackoverflow.com/a/9831340/226181). This scans all logical drives for a file match pattern and ignores the directories that are not accessible.

 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;
        }
    }
你的往事 2024-08-11 02:09:04

最简单的版本:

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

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>();
            }
        }));
}
写给空气的情书 2024-08-11 02:09:04

.Net 4 的 Directory.EnumerateFiles 确实可以工作,但是您必须小心如何评估可枚举值并在 try-catch 块内执行该部分。最大的问题是确保你不会在第一个异常时停止处理(我认为答案https://stackoverflow.com/a上面的/1393219/89584就有这个问题,如果有错请指正)。

以下内容可以为您提供一个可枚举的值,因此如果您正在寻找第一个匹配项等,则不必评估整个文件树。

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

对上述欢迎的改进。

.Net 4's Directory.EnumerateFiles does work, but you've got to be careful how you evaluate the enumerable and do that part inside the try-catch block. The biggest issue is making sure you don't stop processing at the first exception (which I think answer https://stackoverflow.com/a/1393219/89584 above has this problem, please correct me if I'm wrong there).

The following works and gives you an Enumerable so you don't have to evaluate the entire file tree if you're 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 to the above welcome.

很快妥协 2024-08-11 02:09:04
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();
}

这是我对这个问题的解决方案。简单且安全。

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 fail safe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文