【问题标题】:Check if directory is accessible in C#? [duplicate]检查目录是否可在 C# 中访问? [复制]
【发布时间】:2012-07-29 14:07:13
【问题描述】:

可能重复:
.NET - Check if directory is accessible without exception handling

我正在使用 NET 3.5 和 C# 在 Visual Studio 2010 中创建一个小文件浏览器,并且我有这个功能来检查目录是否可访问:

RealPath=@"c:\System Volume Information";
public bool IsAccessible()
{
    //get directory info
    DirectoryInfo realpath = new DirectoryInfo(RealPath);
    try
    {
        //if GetDirectories works then is accessible
        realpath.GetDirectories();                
        return true;
    }
    catch (Exception)
    {
        //if exception is not accesible
        return false;
    }
}

但我认为对于大目录,尝试获取所有子目录以检查目录是否可访问可能会很慢。 我使用此功能来防止在尝试浏览受保护的文件夹或没有光盘的 cd/dvd 驱动器时出错(“设备未就绪”错误)。

是否有更好的方法(更快)来检查应用程序是否可以访问目录(最好在 NET 3.5 中)?

【问题讨论】:

  • 这是否适用于“可访问” Directory.Exists ( Path.Combine( RealPath + "\." ) )
  • 你违背了 Windows 资源管理器的工作方式。为什么不显示不可访问的文件夹?如果用户看不到它,他就不会知道他有一个 CD 驱动器。
  • 用户不知道该目录是否可访问,如果用户双击“不可访问”目录c#返回错误

标签: c# visual-studio-2010 directoryinfo getdirectories


【解决方案1】:

根据MSDN,如果您没有目录的读取权限,Directory.Exists 应该返回 false。但是,您可以为此使用Directory.GetAccessControl。示例:

public static bool CanRead(string path)
{
    try
    {
        var readAllow = false;
        var readDeny = false;
        var accessControlList = Directory.GetAccessControl(path);
        if(accessControlList == null)
            return false;

        //get the access rules that pertain to a valid SID/NTAccount.
        var accessRules = accessControlList.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
        if(accessRules ==null)
           return false;

        //we want to go over these rules to ensure a valid SID has access
        foreach (FileSystemAccessRule rule in accessRules)
        {
            if ((FileSystemRights.Read & rule.FileSystemRights) != FileSystemRights.Read) continue;

            if (rule.AccessControlType == AccessControlType.Allow)
                readAllow = true;
            else if (rule.AccessControlType == AccessControlType.Deny)
                readDeny = true;
        }

        return readAllow && !readDeny;
    }
    catch(UnauthorizedAccessException ex)
    {
        return false;
    }
}

更新

正如某些 cmets 中所述,在外部 DOMAIN 中的有效 SID 具有访问权限的情况下,这可能会返回不正确的值。为了检查当前用户是否具有访问权限,您需要以下内容:

foreach...

if (WindowsIdentity.GetCurrent().User.Value.equals(rule.IdentityReference.Value))

这将确认当前用户的 SID 是否与访问规则身份引用匹配,但也可能抛出 SecurityException。

【讨论】:

  • 不错。 accessRules 是一个集合,并且永远不会为空,因此检查是多余的。最好检查一下集合是否为空。
  • 我在尝试使用此功能时收到此错误。 System.UnauthorizedAccessException was unhandled HResult=-2147024891 Message=Attempted to perform an unauthorized operation.
  • 如果任何用户被拒绝访问,这将返回 false
  • 奇怪的答案。我试图读取另一个用户的桌面文件夹 C:\users\another user\desktop 结果是真的。我试图从我的计算机进入同一个文件夹 - 我不能。
  • 如果accessRule 至少有FileSystemRights.ListDirectory 低于FileSystemRights.Read,我猜foreach 的第一次检查应该继续。这样,在FileSystemRights.ListDirectory 上带有AccessControlType.DenyaccessRule 将被检测到并导致readDeny = true
【解决方案2】:

我认为您正在寻找GetAccessControl 方法,System.IO.File.GetAccessControl 方法返回一个封装文件访问控制的 FileSecurity 对象。

【讨论】:

    猜你喜欢
    • 2014-05-02
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 2016-09-10
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多