在 C# .NET 中,哪些目录可以 Directory.GetDirectories 或 Directory.GetFiles 不能从中获取目录或文件,为什么?

In C# .NET, what directories can Directory.GetDirectories or Directory.GetFiles not get directories or files from, and Why?

在 C# .NET 中,某些传递给 Directory.GetDirectoriesDirectory.GetFiles 的目录会引发异常。那些导致它无法读取的目录究竟是什么?

simpletest1_test_exceptions_with_those_functions(@"C:\");
simpletest1_test_exceptions_with_those_functions(@"C:\windows");

我编写的以下函数 (simpletest1_test_exceptions_with_those_functions) 用于测试 GetDirectories 和 GetFiles,工作正常,它显示无法访问哪些目录,但问题是为什么。

请注意,该函数有意注释掉了很多内容,因为它能够递归地浏览整个目录树,但我已经注释掉了它,因此它只执行目录树的一个级别。它通常会列出所有文件和目录,但我已经评论过了。这样当它无法访问的目录作为参数传递时,它只显示 GetDirectories 函数无法访问的目录。

static void simpletest1_test_exceptions_with_those_functions(string sDir)
{
    // can't just have a try catch at the end otherwise it won't return.

    try 
    {

        Console.WriteLine("DirSearch..(" + sDir + ")");

        //Console.WriteLine(sDir);

        Console.WriteLine("files");
        foreach (string f in Directory.GetFiles(sDir))
        {
            // Console.WriteLine(f);
        }

        Console.WriteLine("directories");
        foreach (string d in Directory.GetDirectories(sDir))
        {
            // testexceptionwiththosefunctions(d);
            // Console.WriteLine(d);

            try
            {
                foreach (string f in Directory.GetFiles(d))
                {
                    // Console.WriteLine(f);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("z Directory.GetFiles threw exception");
                Console.WriteLine(e.Message);
            }
        }
    
    }
    catch(Exception ee)
    {
        Console.WriteLine("some exception thrown");
    }
  
    
}

给予

DirSearch..(C:\)
files
directories
z Directory.GetFiles threw exception
Access to the path 'C:\Documents and Settings' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\MSOCache' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\Recovery' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\System Volume Information' is denied.
-----
DirSearch..(C:\windows)
files
directories
z Directory.GetFiles threw exception
Access to the path 'C:\windows\LiveKernelReports' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\windows\Minidump' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\windows\ModemLogs' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\windows\Prefetch' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\windows\Temp' is denied.

在这些路径之外..“文档和设置”是一个路口,很好,无法处理通过路口的问题。

(dir /a 显示所有目录,无论是隐藏的还是系统的还是只读的,只是全部)

C:\>dir /a | find "Docu"
14/07/2009  06:08    <JUNCTION>     Documents and Settings [C:\Users]

C:\>

尽管此处列出的所有其他目录都没有连接点。

所以并不是说它不能在路口上工作。

此外,我可以 CD 进入 Documents and Settings,我不能进入许多其他目录。我可以 CD 进入 C:\Windows\temp,但其他人我不能

C:\Windows>cd Temp

C:\Windows\Temp>cd ..

C:\Windows>cd LiveKernelReports
Access is denied.

C:\Windows>

是隐藏的还是系统的还是只读的不相关

例如这个目录不是隐藏的或系统的或只读的

C:\Windows>dir | find "Live"
14/07/2009  03:34    <DIR>          LiveKernelReports

C:\Windows>attrib LiveKernelReports
             C:\Windows\LiveKernelReports

C:\Windows>

这不是系统或隐藏的问题,因为Directory.GetFiles和Directory.GetDirectories在这些目录上没有问题。我尝试创建 c:\atest\hdir (其中 hdir 是一个隐藏目录)和 c:\test\sdir (其中 sdir 是一个系统目录)

C:\atest>dir
 Volume in drive C has no label.
 Volume Serial Number is 4645-5DCE

 Directory of C:\atest

17/07/2020  02:45    <DIR>          .
17/07/2020  02:45    <DIR>          ..
17/07/2020  02:44    <DIR>          hdir
17/07/2020  02:45    <DIR>          rdir
17/07/2020  02:44    <DIR>          sdir
               0 File(s)              0 bytes
               5 Dir(s)  286,734,127,104 bytes free

C:\atest>attrib +h hdir

C:\atest>attrib +r rdir

C:\atest>attrib +s sdir

C:\atest>attrib sdir
   S         C:\atest\sdir

C:\atest>attrib hdir
    H        C:\atest\hdir

C:\atest>attrib rdir
     R       C:\atest\rdir

C:\atest>

我使用这个更简单的函数来验证特定路径(传递给 GetFiles 或 GetDirectories)是否抛出异常,并且 hidden/system/read 只有我创建的目录不会抛出异常。

经验证system/read-only/hidden与此无关

static void test_exception_with_thosefunctions()
{
    string[] dirs=null;
    string[] files=null;
    string dirstr="";
    try
    {
        // dirs = Directory.GetDirectories(@"C:\Documents and Settings");
        dirstr = @"c:\atest\hdir";
        dirs = Directory.GetDirectories(dirstr);
        files = Directory.GetFiles(dirstr);

        dirstr = @"c:\atest\rdir";
        dirs = Directory.GetDirectories(dirstr);
        files = Directory.GetFiles(dirstr);

        dirstr = @"c:\atest\sdir";
        dirs = Directory.GetDirectories(dirstr);
        files = Directory.GetFiles(dirstr);

        // files = Directory.GetFiles(@"C:\Documents and Settings");
        Console.WriteLine(dirs.Length);
    }
    catch(Exception e)
    {
        //if(dirs!=null) Console.WriteLine(dirs.Length);
        //if(files!=null) Console.WriteLine(files.Length);
        Console.WriteLine(e.Message);
    }
}

所以我列出的那些路径显然有一些东西会抛出异常..我想知道它们是什么?

简单地说,您没有这些目录的权限。

运行(提升)您的应用程序/命令提示符作为管理员将解决很多问题。

我将接受 TheGeneral 的回答,它涵盖了我提到的大部分目录,但不包括这两个目录 - “文档和设置”和“系统卷信息”。

我发布这个答案是为了涵盖 Eryk Sun 在评论中提到的内容,其中涵盖了这两个目录。

将军对 运行ning 的回答来自管理 cmd 提示,因为有些需要管理权限,当然可以回答其中的许多情况,尽管不是全部

C:\blah>ConsoleApp1.exe
adf
0
DirSearch..(C:\)
files
directories
z Directory.GetFiles threw exception
Access to the path 'C:\Documents and Settings' is denied.
z Directory.GetFiles threw exception
Access to the path 'C:\System Volume Information' is denied.
-----
DirSearch..(C:\windows)
files
directories

所以这表明即使在管理命令提示符下仍然没有读取两个目录。

C:\Documents and Settings目录和'C:\System Volume Information'目录。

Eryk Sun 提到“为了兼容挂载点(又名连接点),每个人 (S-1-1-0) 都被拒绝列出目录的权利。它们的存在只是为了遍历以访问子目录(例如 dir "C :\Documents 和 Settings\Public")。这与它们是挂载点这一事实毫无关系。它只是目录上设置的自由访问控制列表的一个功能。"

Eryk 提到“ icacls“C:\Documents and Settings”应该有一个针对每个人的拒绝条目 (S-1-1-0),但是组的友好名称已本地化(检查 sysinternals psgetsid s-1-1-0)。大多数文件夹不会向所有人授予访问权限。通常,他们授予访问权限的组,例如“经过身份验证的用户”(S-1-5-11)、系统 (S-1-5-18)、管理员 (S-1-5-32-544) 和用户 (S -1-5-32-545) “

确实 icacls "C:\Documents and Settings" 确实显示了每个人的拒绝条目

C:\Windows\system32>icacls "C:\Documents and Settings"
C:\Documents and Settings Everyone:(DENY)(S,RD)
                          Everyone:(RX)
                          NT AUTHORITY\SYSTEM:(F)
                          BUILTIN\Administrators:(F)

Successfully processed 1 files; Failed processing 0 files

这样就剩下 C:\System Volume Information 剩下的谜团了。

Eryk 提到“通常不会授予任何访问权限,除非它是由自由访问控制列表 (DACL) 中的条目特别授予的。在“C:\System Volume Information”的情况下,只有 SYSTEM 组 (S-1 -5-18) 被授予访问权限。通常只有系统服务 运行 在 SYSTEM 进程中。您可以通过 sysinternals psexec 运行 作为 SYSTEM,例如 psexec -sid cmd.exe 并检查 whoami 在打开命令提示符。

并且 Eryk 提到“DACL 规则有一些常见的例外情况。对象的所有者被隐式授予 READ_CONTROL 和 WRITE_DAC 访问权限以能够读取和修改 DACL,并且所有用户都拥有的 SeChangeNotifyPrivilege 允许将目录遍历到其子目录,即使没有授予对目录的访问权限

确实,如果我 运行 那个 psexec 命令 psexec -sid cmd.exe 以便 运行 cmd.exe 作为系统用户,那么我可以 CD 进入并列出系统卷信息目录。而whoami显示是系统用户

C:\Windows\system32>cd "\System Volume Information"

C:\System Volume Information>dir
 Volume in drive C has no label.
 Volume Serial Number is 4645-5DCE

 Directory of C:\System Volume Information

26/12/2019  11:39        50,790,280 smartdb_Volume{f0f46b52-75c5-11e6-87ea-806e6
f6e6963}.sdb
18/07/2020  19:21         2,621,440 Syscache.hve
24/04/2020  02:39    <DIR>          Windows Backup
24/04/2020  16:06    <DIR>          WindowsImageBackup
               2 File(s)     53,411,720 bytes
               2 Dir(s)  289,325,735,936 bytes free

C:\System Volume Information>whoami
nt authority\system

C:\System Volume Information>