在结束我的问题之前,请看看我在这个问题的末尾检查了哪些不起作用
问题
我一直在尝试各种 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:
- How do you check for permissions to write to a directory or file?
- How to check Read and write permissions on folder in C#
当我这样做时,代码进入 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/