排除和忽略系统文件对我不起作用
Excepting and ignoring system files isn't working for me
在你对这个问题投反对票之前,你需要知道我在这上面花了一些时间而且我有些困惑。我浏览了几个答案,但几乎所有答案都有评论说这是一个很好的解决方案,或者在很多情况下都行不通。
问题归根结底是程序在排除错误后关闭。
示例如下。
C# Test if user has write access to a folder
一些代码:
public static void CcnDirSearch(string sDir) // This is the directory I am passing c:\ to here
{
try
{
foreach (string file in Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories)) // File is supposed to hold the individual file...
{
bool isSystem = ((File.GetAttributes(file) & FileAttributes.System) == FileAttributes.System);
if (HasFolderWritePermission(file) == true && isSystem == false && file != @"c:$Recycle.Bin\S-1-5-18")
{
Console.WriteLine(file);
using (var stream = File.OpenRead(file))
{
// I am checking file here with my own functions.
}
}
}
}
catch (UnauthorizedAccessException ex)
{
//User cannot access directory
Console.WriteLine("I AM NOT CONTINUING " + ex.Message);
}
catch (System.Exception excpt)
{
// Console.WriteLine("I AM AN ERROR!!!\n");
Console.WriteLine(excpt.Message);
}
}
我收到的错误是
我不会继续访问路径 'c:$Recycle.Bin\S-1-5-18' 被拒绝。
那么我的程序就存在了
是的,我已经查过了,到目前为止的所有示例似乎都没有完全涵盖这一点。
捕获异常后继续执行
The problem ultimately is that the program closes after excepting the error.
所以你的真正的问题是程序在catch
块之后退出?
嗯,如果捕获到异常,你的问题不会继续执行的原因是你在最后一个 catch
-block 之后没有任何代码,所以程序退出,因为没有更多的东西了做。
查看这个简化的代码示例
public static void Main(string[] args)
{
try
{
throw new UnauthorizedAccessException("Cannot access this path.");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"I am not continuing. Reason: {e.Message}.");
}
// Important, otherwise we would simply exit.
Console.WriteLine("Or look, I am in fact continuing :)"); }
打印
I am not continuing. Reason: Cannot access this path.
Or look, I am in fact continuing :)
因此,为了让您的程序在 catch
块之后 而不是 退出并继续执行,您需要在它们之后放置一些代码。
获取文件夹及其子文件夹中的所有文件
正如 OP 在评论中所解释的那样,真正的 问题是他们想要遍历特定文件夹及其子文件夹中的每个文件,但不想如果他们无权访问文件或文件夹,则停止。
因此,我想出了下面的方法
public static IEnumerable<string> GetAllAccessibleFilesIn(string rootDirectory, string searchPattern = "*.*")
{
List<string> files = new List<string>();
try
{
files.AddRange(Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly));
foreach (string directory in Directory.GetDirectories(rootDirectory))
{
files.AddRange(GetAllAccessibleFilesIn(directory, searchPattern));
}
}
catch (UnauthorizedAccessException)
{
// Don't do anything if we cannot access a file.
}
return files;
}
使用起来像
IEnumerable<string> allFiles = GetAllAccessibleFilesIn(@"C:\");
生成 C:\
或其任何子文件夹中的所有可访问文件。
添加评论有点长。您的问题可能出在 Directory.EnumerateFiles()
这里有一个link可以帮到你:
DirectoryInfo.EnumerateFiles(...) causes UnauthorizedAccessException (and other exceptions)
此外,添加 Pathtoolongexception 会很棒
并检查 Directory.Exists 等。
您可能有如下所示的布尔方法:
bool CanAccessDirectory(string sDir)
{
if (!Directory.Exists(sDir)) return false;
try {
IEnumerable files = Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories);
}
catch(UnauthorizedException exc)
{ return false; }
catch(PathtooLongException ex)
{ return false; }
// we reach here
return true;
}
文件访问出错的方式有很多种。检查您的代码没有帮助,因为可以删除文件,并且可以在检查和读取文件之间更改权限。
我已经包含了正确的检查来演示如何检查访问控制。请注意,您将 file 发送到 directory检查。
public static bool HasFileReadPermission(string fullPathToFile)
{
var accessControlList = File.GetAccessControl(fullPathToFile);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true,
typeof(System.Security.Principal.SecurityIdentifier));
bool allow = false, deny = false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) == 0)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
allow = true;
if (rule.AccessControlType == AccessControlType.Deny)
deny = true;
}
return allow || !deny;
}
public static bool HasDirectoryReadPermission(string directory)
{
var accessControlList = Directory.GetAccessControl(directory);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true,
typeof(System.Security.Principal.SecurityIdentifier));
bool allow = false, deny = false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) == 0)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
allow = true;
if (rule.AccessControlType == AccessControlType.Deny)
deny = true;
}
return allow || !deny;
}
public static IEnumerable<string> GetAllAccessibleFilesIn(string rootDirectory, string searchPattern = "*.*")
{
foreach (string directoryAndFileName in Directory.EnumerateFiles(rootDirectory, "*.*", SearchOption.AllDirectories))
{
var directory = Path.GetDirectoryName(directoryAndFileName);
// Start by checking the directory
if (!HasDirectoryReadPermission(directory))
continue;
var isSystem = (File.GetAttributes(directoryAndFileName) & FileAttributes.System) != 0;
try
{
// Skip files that are system files or inaccessible
if (!HasFileReadPermission(directoryAndFileName) || isSystem)
continue;
Console.WriteLine(directoryAndFileName);
using (var stream = File.OpenRead(directoryAndFileName))
{
// I am checking file here with my own functions.
}
}
catch (UnauthorizedAccessException ex)
{
// Things can change, guard against errors
Console.WriteLine("I AM NOT CONTINUING " + ex.Message);
}
catch (IOException ex)
{
// Other IO (file operation) exceptions
// don't catch "Exception" as that can hide non-related errors.
Console.WriteLine(ex.Message);
}
}
}
在你对这个问题投反对票之前,你需要知道我在这上面花了一些时间而且我有些困惑。我浏览了几个答案,但几乎所有答案都有评论说这是一个很好的解决方案,或者在很多情况下都行不通。
问题归根结底是程序在排除错误后关闭。
示例如下。
C# Test if user has write access to a folder
一些代码:
public static void CcnDirSearch(string sDir) // This is the directory I am passing c:\ to here
{
try
{
foreach (string file in Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories)) // File is supposed to hold the individual file...
{
bool isSystem = ((File.GetAttributes(file) & FileAttributes.System) == FileAttributes.System);
if (HasFolderWritePermission(file) == true && isSystem == false && file != @"c:$Recycle.Bin\S-1-5-18")
{
Console.WriteLine(file);
using (var stream = File.OpenRead(file))
{
// I am checking file here with my own functions.
}
}
}
}
catch (UnauthorizedAccessException ex)
{
//User cannot access directory
Console.WriteLine("I AM NOT CONTINUING " + ex.Message);
}
catch (System.Exception excpt)
{
// Console.WriteLine("I AM AN ERROR!!!\n");
Console.WriteLine(excpt.Message);
}
}
我收到的错误是
我不会继续访问路径 'c:$Recycle.Bin\S-1-5-18' 被拒绝。
那么我的程序就存在了
是的,我已经查过了,到目前为止的所有示例似乎都没有完全涵盖这一点。
捕获异常后继续执行
The problem ultimately is that the program closes after excepting the error.
所以你的真正的问题是程序在catch
块之后退出?
嗯,如果捕获到异常,你的问题不会继续执行的原因是你在最后一个 catch
-block 之后没有任何代码,所以程序退出,因为没有更多的东西了做。
查看这个简化的代码示例
public static void Main(string[] args)
{
try
{
throw new UnauthorizedAccessException("Cannot access this path.");
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine($"I am not continuing. Reason: {e.Message}.");
}
// Important, otherwise we would simply exit.
Console.WriteLine("Or look, I am in fact continuing :)"); }
打印
I am not continuing. Reason: Cannot access this path.
Or look, I am in fact continuing :)
因此,为了让您的程序在 catch
块之后 而不是 退出并继续执行,您需要在它们之后放置一些代码。
获取文件夹及其子文件夹中的所有文件
正如 OP 在评论中所解释的那样,真正的 问题是他们想要遍历特定文件夹及其子文件夹中的每个文件,但不想如果他们无权访问文件或文件夹,则停止。
因此,我想出了下面的方法
public static IEnumerable<string> GetAllAccessibleFilesIn(string rootDirectory, string searchPattern = "*.*")
{
List<string> files = new List<string>();
try
{
files.AddRange(Directory.GetFiles(rootDirectory, searchPattern, SearchOption.TopDirectoryOnly));
foreach (string directory in Directory.GetDirectories(rootDirectory))
{
files.AddRange(GetAllAccessibleFilesIn(directory, searchPattern));
}
}
catch (UnauthorizedAccessException)
{
// Don't do anything if we cannot access a file.
}
return files;
}
使用起来像
IEnumerable<string> allFiles = GetAllAccessibleFilesIn(@"C:\");
生成 C:\
或其任何子文件夹中的所有可访问文件。
添加评论有点长。您的问题可能出在 Directory.EnumerateFiles()
这里有一个link可以帮到你:
DirectoryInfo.EnumerateFiles(...) causes UnauthorizedAccessException (and other exceptions)
此外,添加 Pathtoolongexception 会很棒
并检查 Directory.Exists 等。
您可能有如下所示的布尔方法:
bool CanAccessDirectory(string sDir)
{
if (!Directory.Exists(sDir)) return false;
try {
IEnumerable files = Directory.EnumerateFiles(sDir, "*.*", SearchOption.AllDirectories);
}
catch(UnauthorizedException exc)
{ return false; }
catch(PathtooLongException ex)
{ return false; }
// we reach here
return true;
}
文件访问出错的方式有很多种。检查您的代码没有帮助,因为可以删除文件,并且可以在检查和读取文件之间更改权限。
我已经包含了正确的检查来演示如何检查访问控制。请注意,您将 file 发送到 directory检查。
public static bool HasFileReadPermission(string fullPathToFile)
{
var accessControlList = File.GetAccessControl(fullPathToFile);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true,
typeof(System.Security.Principal.SecurityIdentifier));
bool allow = false, deny = false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) == 0)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
allow = true;
if (rule.AccessControlType == AccessControlType.Deny)
deny = true;
}
return allow || !deny;
}
public static bool HasDirectoryReadPermission(string directory)
{
var accessControlList = Directory.GetAccessControl(directory);
if (accessControlList == null)
return false;
var accessRules = accessControlList.GetAccessRules(true, true,
typeof(System.Security.Principal.SecurityIdentifier));
bool allow = false, deny = false;
foreach (FileSystemAccessRule rule in accessRules)
{
if ((FileSystemRights.Read & rule.FileSystemRights) == 0)
continue;
if (rule.AccessControlType == AccessControlType.Allow)
allow = true;
if (rule.AccessControlType == AccessControlType.Deny)
deny = true;
}
return allow || !deny;
}
public static IEnumerable<string> GetAllAccessibleFilesIn(string rootDirectory, string searchPattern = "*.*")
{
foreach (string directoryAndFileName in Directory.EnumerateFiles(rootDirectory, "*.*", SearchOption.AllDirectories))
{
var directory = Path.GetDirectoryName(directoryAndFileName);
// Start by checking the directory
if (!HasDirectoryReadPermission(directory))
continue;
var isSystem = (File.GetAttributes(directoryAndFileName) & FileAttributes.System) != 0;
try
{
// Skip files that are system files or inaccessible
if (!HasFileReadPermission(directoryAndFileName) || isSystem)
continue;
Console.WriteLine(directoryAndFileName);
using (var stream = File.OpenRead(directoryAndFileName))
{
// I am checking file here with my own functions.
}
}
catch (UnauthorizedAccessException ex)
{
// Things can change, guard against errors
Console.WriteLine("I AM NOT CONTINUING " + ex.Message);
}
catch (IOException ex)
{
// Other IO (file operation) exceptions
// don't catch "Exception" as that can hide non-related errors.
Console.WriteLine(ex.Message);
}
}
}