在 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.GetDirectories
或 Directory.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>
在 C# .NET 中,某些传递给 Directory.GetDirectories
或 Directory.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>