C# - 检查是否可以访问/读取文件夹

标签 c# permissions filesystemobject directoryinfo system.io.directory

在结束我的问题之前,请看看我在这个问题的末尾检查了哪些不起作用


问题

我一直在尝试各种 SO 答案,所有这些都给我带来了一个异常(exception),除了其中许多听起来对于应该非常简单的事情来说过于复杂。

如何在执行之前检查我是否有权枚举文件夹的内容? (我不想尝试/捕获,因为我正在遍历文件系统并且多次尝试/捕获会影响 C# 上的性能)

每当我尝试以下操作时:

//where dir is a DirectoryInfo instance
foreach (FileInfo file in dir.EnumerateFiles())

我得到这个异常:

An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
Additional information: O acesso ao caminho 'e:\$RECYCLE.BIN\S-1-5-18' foi negado.
translation:"Access to the path 'e:\$RECYCLE.BIN\S-1-5-18' was denied"


什么不起作用:

1:

当我这样做时,代码进入 if 并在命中枚举时抛出相同的异常。

PermissionSet permissions = new PermissionSet(System.Security.Permissions.PermissionState.None);
permissions.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, dir.FullName));

if (permissions.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))

2:

以下引发异常:

DirectorySecurity security = dir.GetAccessControl(AccessControlSections.All); 

异常(exception):

An unhandled exception of type 'System.Security.AccessControl.PrivilegeNotHeldException' occurred in mscorlib.dll
Additional information: O processo não possui o privilégio 'SeSecurityPrivilege' necessário para esta operação.
translation: The process doesn't have the 'SeSecurityPrivilege' privilege necessary for this operation.

还有:

    DirectorySecurity security = dir.GetAccessControl(AccessControlSections.None); 

异常(exception):

An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll
Additional information: Tentativa de execução de uma operação não autorizada.
translation: Attempting to execute an unauthorized operation

3:

尝试过:

DirectorySecurity security = Directory.GetAccessControl(dir.FullName);

与上述相同的异常。

最佳答案

这似乎是一个很好的问题,可以发布我的 SafeWalk 类(class),该类(class)将来自多个答案的提示聚集在一起。它能够在我的盒子上遍历 C:\和 D:\而不会造成问题。

public static class SafeWalk {
    [Flags]
    public enum ReturnOptions {
        ReturnFiles = 1, ReturnDirectories = 2, ReturnBoth = 3
    }

    const string AllFiles = "*.*";

    // File and Directory Name Tree Walkers

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this DirectoryInfo di, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.FullName.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnBoth);

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this DirectoryInfo di, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.FullName.SafeEnumerateFileAndDirNames(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnBoth);

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this DirectoryInfo di, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.FullName.SafeEnumerateFileAndDirNames(filePattern, dirPattern, searchOpt, ReturnOptions.ReturnBoth);

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnBoth);

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this string path, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnBoth);

    public static IEnumerable<string> SafeEnumerateFileAndDirNames(this string path, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) {
        var searchQueue = new Queue<string>() { path };

        while (searchQueue.Count > 0) {
            var cdn = searchQueue.Dequeue();

            IEnumerable<string> cdiFiles = null;
            if (returnOpt.HasFlag(ReturnOptions.ReturnFiles)) {
                try {
                    cdiFiles = Directory.EnumerateFiles(cdn, filePattern, SearchOption.TopDirectoryOnly);
                }
                catch (Exception) {
                }

                if (cdiFiles != null)
                    foreach (var filename in cdiFiles)
                        yield return filename;
            }

            if ((!returnOpt.HasFlag(ReturnOptions.ReturnFiles) || cdiFiles != null) && (returnOpt.HasFlag(ReturnOptions.ReturnDirectories) || searchOpt == SearchOption.AllDirectories)) { // skip if file enumeration failed
                IEnumerable<string> cdiDirs = null;
                try {
                    cdiDirs = Directory.EnumerateDirectories(cdn, dirPattern, SearchOption.TopDirectoryOnly);
                }
                catch (Exception) {
                }

                if (cdiDirs != null) {
                    foreach (var dirname in cdiDirs) {
                        if (searchOpt == SearchOption.AllDirectories)
                            searchQueue.Enqueue(dirname);

                        if (returnOpt.HasFlag(ReturnOptions.ReturnDirectories))
                            yield return dirname;
                    }
                }
            }
        }
    }

    public static IEnumerable<string> SafeEnumerateFileNames(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateFileNames(this string path, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateFileNames(this string path, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(filePattern, dirPattern, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateFileNames(this DirectoryInfo path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.FullName.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateFileNames(this DirectoryInfo path, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.FullName.SafeEnumerateFileAndDirNames(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateFileNames(this DirectoryInfo path, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.FullName.SafeEnumerateFileAndDirNames(filePattern, dirPattern, searchOpt, ReturnOptions.ReturnFiles);

    public static IEnumerable<string> SafeEnumerateDirectoryNames(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnDirectories);

    public static IEnumerable<string> SafeEnumerateDirectoryNames(this string path, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.SafeEnumerateFileAndDirNames(AllFiles, dirPattern, searchOpt, ReturnOptions.ReturnDirectories);

    public static IEnumerable<string> SafeEnumerateDirectoryNames(this DirectoryInfo path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.FullName.SafeEnumerateFileAndDirNames(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnDirectories);

    public static IEnumerable<string> SafeEnumerateDirectoryNames(this DirectoryInfo path, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        path.FullName.SafeEnumerateFileAndDirNames(AllFiles, dirPattern, searchOpt, ReturnOptions.ReturnDirectories);

    // File and Directory Info Tree Walkers

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, returnOpt);

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this string path, string searchPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(searchPattern, searchPattern, searchOpt, returnOpt);

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this string path, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(filePattern, dirPattern, searchOpt, returnOpt);

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this DirectoryInfo di, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) =>
        di.SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, returnOpt);

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this DirectoryInfo di, string searchPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) =>
        di.SafeEnumerateFileSystemInfos(searchPattern, searchPattern, searchOpt, returnOpt);

    public static IEnumerable<FileSystemInfo> SafeEnumerateFileSystemInfos(this DirectoryInfo di, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly, ReturnOptions returnOpt = ReturnOptions.ReturnBoth) {
        var searchQueue = new Queue<DirectoryInfo>();
        searchQueue.Enqueue(di);
        while (searchQueue.Count > 0) {
            var cdi = searchQueue.Dequeue();

            IEnumerable<string> cdiFiles = null;
            if (returnOpt.HasFlag(ReturnOptions.ReturnFiles)) {
                try {
                    cdiFiles = Directory.EnumerateFiles(cdi.FullName, filePattern, SearchOption.TopDirectoryOnly);
                }
                catch (Exception) {
                }

                if (cdiFiles != null) {
                    var cfis = new ConcurrentBag<FileInfo>();
                    cdiFiles.AsParallel()
                            .ForAll(f => {
                                try {
                                    cfis.Add(new FileInfo(f));
                                }
                                catch (Exception) {
                                }
                            });

                    foreach (var fi in cfis)
                        yield return fi;
                }
            }

            if ((!returnOpt.HasFlag(ReturnOptions.ReturnFiles) || cdiFiles != null) && (returnOpt.HasFlag(ReturnOptions.ReturnDirectories) || searchOpt.HasFlag(SearchOption.AllDirectories))) { // skip if file enumeration failed
                IEnumerable<string> cdiDirs = null;
                try {
                    cdiDirs = Directory.EnumerateDirectories(cdi.FullName, dirPattern, SearchOption.TopDirectoryOnly);
                }
                catch (Exception) {
                }

                if (cdiDirs != null) {
                    var cdis = new ConcurrentBag<DirectoryInfo>();
                    cdiDirs.AsParallel()
                           .ForAll(d => {
                               try {
                                   cdis.Add(new DirectoryInfo(d));
                               }
                               catch (Exception) {
                               }
                           });
                    foreach (var rdi in cdis) {
                        if (returnOpt.HasFlag(ReturnOptions.ReturnDirectories))
                            yield return rdi;
                        if (searchOpt == SearchOption.AllDirectories)
                            searchQueue.Enqueue(rdi);
                    }
                }
            }
        }
    }

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this string path, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this string path, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(filePattern, dirPattern, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this DirectoryInfo di, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this DirectoryInfo di, string filePattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.SafeEnumerateFileSystemInfos(filePattern, AllFiles, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<FileInfo> SafeEnumerateFileInfos(this DirectoryInfo di, string filePattern, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.SafeEnumerateFileSystemInfos(filePattern, dirPattern, searchOpt, ReturnOptions.ReturnFiles).Cast<FileInfo>();

    public static IEnumerable<DirectoryInfo> SafeEnumerateDirectoryInfos(this string path, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnDirectories).Cast<DirectoryInfo>();

    public static IEnumerable<DirectoryInfo> SafeEnumerateDirectoryInfos(this string path, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        new DirectoryInfo(path).SafeEnumerateFileSystemInfos(AllFiles, dirPattern, searchOpt, ReturnOptions.ReturnDirectories).Cast<DirectoryInfo>();

    public static IEnumerable<DirectoryInfo> SafeEnumerateDirectoryInfos(this DirectoryInfo di, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.SafeEnumerateFileSystemInfos(AllFiles, AllFiles, searchOpt, ReturnOptions.ReturnDirectories).Cast<DirectoryInfo>();

    public static IEnumerable<DirectoryInfo> SafeEnumerateDirectoryInfos(this DirectoryInfo di, string dirPattern, SearchOption searchOpt = SearchOption.TopDirectoryOnly) =>
        di.SafeEnumerateFileSystemInfos(AllFiles, dirPattern, searchOpt, ReturnOptions.ReturnDirectories).Cast<DirectoryInfo>();
}

关于C# - 检查是否可以访问/读取文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60194501/

相关文章:

vba - 使用 FileSystemObject 读取和写入 csv 文件

c# - 如何管理多个不断增长的列表?

c# - 为什么我的并行任务代码无法达到100%的CPU使用率?

c# - 如何在C#中运行具有所需权限的bat文件

java - 无需 READ_PHONE_STATE 权限即可使用 TelephonyManager

vbscript - 为什么 FileExists 不支持通配符?

c# - 如何使用C#在MYSQL中建立连接后定义数据库

c# - 获取 Silverlight 5 部署路径(在浏览器中以完全信任模式运行时)

Android 权限,需要 ="false",失败

vba - 传递现有的 FileSystemObject 或创建多个实例