我需要测试用户是否可以在实际尝试这样做之前写入文件夹。

我已经实现了以下方法(在c# 2.0中),它尝试使用Directory.GetAccessControl()方法检索文件夹的安全权限。

private bool hasWriteAccessToFolder(string folderPath)
{
    try
    {
        // Attempt to get a list of security permissions from the folder. 
        // This will raise an exception if the path is read only or do not have access to view the permissions. 
        System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
        return true;
    }
    catch (UnauthorizedAccessException)
    {
        return false;
    }
}

当我在谷歌上搜索如何测试写访问权限时,没有这样的结果,而且在Windows中测试权限看起来非常复杂。我担心我过于简化了事情,这个方法并不健壮,尽管它似乎确实有效。

我测试当前用户是否具有写访问权限的方法是否正确?


当前回答

我无法让GetAccessControl()在Windows 7上抛出一个异常,就像接受的答案中建议的那样。

我最终使用了sdds的答案的变体:

        try
        {
            bool writeable = false;
            WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            DirectorySecurity security = Directory.GetAccessControl(pstrPath);
            AuthorizationRuleCollection authRules = security.GetAccessRules(true, true, typeof(SecurityIdentifier));

            foreach (FileSystemAccessRule accessRule in authRules)
            {

                if (principal.IsInRole(accessRule.IdentityReference as SecurityIdentifier))
                {
                    if ((FileSystemRights.WriteData & accessRule.FileSystemRights) == FileSystemRights.WriteData)
                    {
                        if (accessRule.AccessControlType == AccessControlType.Allow)
                        {
                            writeable = true;
                        }
                        else if (accessRule.AccessControlType == AccessControlType.Deny)
                        {
                            //Deny usually overrides any Allow
                            return false;
                        }

                    } 
                }
            }
            return writeable;
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }

希望这能有所帮助。

其他回答

我试过大多数方法,但都是假阳性,都是出于同样的原因。仅仅测试目录是否有可用权限是不够的,您必须检查登录用户是否是具有该权限的组的成员。为此,您需要获取用户标识,并检查它是否是包含FileSystemAccessRule IdentityReference的组的成员。我已经测试过了,工作完美无缺..

    /// <summary>
    /// Test a directory for create file access permissions
    /// </summary>
    /// <param name="DirectoryPath">Full path to directory </param>
    /// <param name="AccessRight">File System right tested</param>
    /// <returns>State [bool]</returns>
    public static bool DirectoryHasPermission(string DirectoryPath, FileSystemRights AccessRight)
    {
        if (string.IsNullOrEmpty(DirectoryPath)) return false;

        try
        {
            AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
            WindowsIdentity identity = WindowsIdentity.GetCurrent();

            foreach (FileSystemAccessRule rule in rules)
            {
                if (identity.Groups.Contains(rule.IdentityReference))
                {
                    if ((AccessRight & rule.FileSystemRights) == AccessRight)
                    {
                        if (rule.AccessControlType == AccessControlType.Allow)
                            return true;
                    }
                }
            }
        }
        catch { }
        return false;
    }

以我之见,唯一100%可靠的测试是否可以写入目录的方法是实际写入并最终捕获异常。

这应该是您所需要的全部内容,据我所知,您只需要捕获一个异常。

private static readonly byte[] TestArray = new byte[]{
    69, 70, 71, 72
};

private static bool IsFolderAccessible(string path) {
    var temp_path = Path.Combine(path, Path.GetRandomFileName());

    try {
        using (var file = File.Create(temp_path, TestArray.Length, FileOptions.DeleteOnClose)) {
            file.Write(TestArray, 0, TestArray.Length);
        }

        return true;
    } catch (UnauthorizedAccessException ex) {
        Log.Warn($"Error accessing file {temp_path}", ex);

        return false;
    }
}
public bool IsDirectoryWritable(string dirPath, bool throwIfFails = false)
{
    try
    {
        using (FileStream fs = File.Create(
            Path.Combine(
                dirPath, 
                Path.GetRandomFileName()
            ), 
            1,
            FileOptions.DeleteOnClose)
        )
        { }
        return true;
    }
    catch
    {
        if (throwIfFails)
            throw;
        else
            return false;
    }
}

仅仅尝试访问有问题的文件是不够的。测试将在运行程序的用户的权限下运行——这并不一定是您想要测试的用户权限。