如何检查Windows文件是否可读/可写?

时间:2022-06-01 13:32:50

First off: I know that this isn't reliable for actually checking if I can write. I'm writing a file transfer client, and want feature parity between the "remote" and "local" file browser panes. I fully understand I will have to handle any permission related exceptions for any operation performed regardless; it's not a programming check it's just to display to the user.

首先:我知道这实际上是否可以写,这是不可靠的。我正在编写文件传输客户端,并希望在“远程”和“本地”文件浏览器窗格之间进行功能奇偶校验。我完全理解,无论如何,我都必须处理任何与许可相关的异常;它不是一个编程检查它只是显示给用户。

I've seen several examples for these posted, but everything I've tried either wasn't understandable or didn't work. I've tried the following two methods, but both just returned "yes" for things I definitely can't write to (the contents of C:\Windows or C:\Program Files, for example):

我已经看到了这些发布的几个例子,但我尝试的一切都是不可理解的或不起作用。我已经尝试了以下两种方法,但是对于我绝对无法写入的内容(例如C:\ Windows或C:\ Program Files的内容),它们都只返回“是”:

System.Security.Permissions.FileIOPermission fp = new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.Write, Path);
return System.Security.SecurityManager.IsGranted(fp);

and

System.Security.Permissions.FileIOPermission fp = new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.Write, element.Path);
try
{
    fp.Assert();
    return true;
}
catch(Exception x)
{
    return false;
}

(Again, I'm aware that both catching Exception is horrible and using try/catch for logic is slightly less horrible, I'm just trying to get this to work).

(同样,我知道捕获异常都很糟糕,使用try / catch进行逻辑操作稍微不那么可怕,我只是想让它工作)。

The first one tells me that IsGranted is deprecated and I should be using AppDomain.PermissionSet or Application.PermissionSet, but I can't find any explanation of how to use these that makes sense. I've also seen that I should be manually enumerating all the ACLs to figure it out myself, but again there's no real examples of this. There's quite a few examples for setting permissions, but few for checking them.

第一个告诉我IsGranted已被弃用,我应该使用AppDomain.PermissionSet或Application.PermissionSet,但我找不到任何解释如何使用这些有意义。我也看到我应该手动枚举所有ACL来自己弄清楚,但同样没有真正的例子。设置权限有很多示例,但很少用于检查权限。

Any help would be greatly appreciated.

任何帮助将不胜感激。

1 个解决方案

#1


2  

Well, here's what I eventually wound up with:

好吧,这就是我最终结果:

    private readonly static WindowsIdentity _identity = WindowsIdentity.GetCurrent();
    protected static bool GetPermission(FileSystemRights right, string path)
    {
        FileSecurity fs;
        try
        {
            fs = System.IO.File.GetAccessControl(path);
        }
        catch(InvalidOperationException)
        {
            // called on a disk that's not present, ...
            return false;
        }
        catch(UnauthorizedAccessException)
        {
            return false;
        }
        foreach(FileSystemAccessRule fsar in fs.GetAccessRules(true, true, typeof(SecurityIdentifier)))
        {
            if(fsar.IdentityReference == _identity.User && fsar.FileSystemRights.HasFlag(right) && fsar.AccessControlType == AccessControlType.Allow)
            {
                return true;
            }
            else if(_identity.Groups.Contains(fsar.IdentityReference) && fsar.FileSystemRights.HasFlag(right) && fsar.AccessControlType == AccessControlType.Allow)
            {
                return true;
            }
        }
        return false;
    }

Of course, it's not ideal, because it ignores Deny rights. But I have no idea in which order to apply the various ACEs (I think?) in order to find out the "correct" ability. Still, Deny rules are relatively rare, so it works most of the time for me.

当然,这并不理想,因为它忽略了Deny的权利。但我不知道以哪种顺序应用各种ACE(我认为?)以找出“正确”的能力。但是,拒绝规则相对较少,因此它对我来说大部分时间都有效。

#1


2  

Well, here's what I eventually wound up with:

好吧,这就是我最终结果:

    private readonly static WindowsIdentity _identity = WindowsIdentity.GetCurrent();
    protected static bool GetPermission(FileSystemRights right, string path)
    {
        FileSecurity fs;
        try
        {
            fs = System.IO.File.GetAccessControl(path);
        }
        catch(InvalidOperationException)
        {
            // called on a disk that's not present, ...
            return false;
        }
        catch(UnauthorizedAccessException)
        {
            return false;
        }
        foreach(FileSystemAccessRule fsar in fs.GetAccessRules(true, true, typeof(SecurityIdentifier)))
        {
            if(fsar.IdentityReference == _identity.User && fsar.FileSystemRights.HasFlag(right) && fsar.AccessControlType == AccessControlType.Allow)
            {
                return true;
            }
            else if(_identity.Groups.Contains(fsar.IdentityReference) && fsar.FileSystemRights.HasFlag(right) && fsar.AccessControlType == AccessControlType.Allow)
            {
                return true;
            }
        }
        return false;
    }

Of course, it's not ideal, because it ignores Deny rights. But I have no idea in which order to apply the various ACEs (I think?) in order to find out the "correct" ability. Still, Deny rules are relatively rare, so it works most of the time for me.

当然,这并不理想,因为它忽略了Deny的权利。但我不知道以哪种顺序应用各种ACE(我认为?)以找出“正确”的能力。但是,拒绝规则相对较少,因此它对我来说大部分时间都有效。