排除和忽略系统文件对我不起作用

时间:2018-09-11 09:22:17

标签: c# exception exception-handling

在对问题投反对票之前,您需要知道我花了一些时间在此上,我有些困惑。我浏览了几个答案,但是几乎所有答案都说这是一个很好的解决方案,或者在很多情况下都行不通。

最终,问题是该程序在排除了错误之后关闭了。

以下示例。

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'被拒绝。

然后我的程序存在。

是的,我已经查过,到目前为止,所有示例似乎都没有完全涵盖这一点。

3 个答案:

答案 0 :(得分:4)

捕获异常后继续执行

  

问题最终是该程序在排除错误后关闭。

您的实际问题是程序在catch块之后退出了吗?

好吧,如果捕获到异常,您的问题就不会继续执行的原因是,在最后一个catch块之后您没有任何代码,因此该程序退出了,因为无事可做。

查看此简化的代码示例

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 :)");     }

可打印

  

我没有继续。原因:无法访问此路径。

     

或者,我实际上正在继续:)

因此,为了使程序在catch块之后 not 不退出并继续执行,您需要在它们之后放置一些代码。


获取文件夹及其子文件夹中的所有文件

正如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:\或其任何子文件夹中的每个可访问文件。

答案 1 :(得分:0)

这有点长,无法添加为评论。您的问题可能出在Directory.EnumerateFiles()

以下是可以帮助您的链接:

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;
}

答案 2 :(得分:0)

文件访问出错的方法有很多种。在代码中进行检查无济于事,因为可以删除文件,并且可以在检查和读取文件之间更改权限。

我提供了正确的检查,以演示如何检查访问控制。请注意,您将 文件 发送到 目录 检查。

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);
        }

    }
}