C# 测试用户是否有文件夹的写权限

发布于 2024-08-04 15:56:43 字数 828 浏览 4 评论 0原文

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

我已经实现了以下方法(在 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 中实际测试权限似乎非常复杂。我担心我过于简化了事情,而且这种方法并不稳健,尽管它似乎确实有效。

我测试当前用户是否具有写入权限的方法可以正常工作吗?

I need to test if a user can write to a folder before actually attempting to do so.

I've implemented the following method (in C# 2.0) that attempts to retrieve the security permissions for the folder using Directory.GetAccessControl() method.

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

When I was googling how to test for write access nothing like this came up and it appeared very complicated to actually test permissions in Windows. I am concerned that I am over-simplifying things and that this method is not robust, although it does seem to work.

Will my method to test if the current user has write access work correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

九厘米的零° 2024-08-11 15:56:43
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;
    }
}
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;
    }
}
腹黑女流氓 2024-08-11 15:56:43

我很高兴这篇文章发布的时间有点晚,但您可能会发现这段代码很有用。

string path = @"c:\temp";
string NtAccountName = @"MyDomain\MyUserOrGroup";

DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All);
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

//Go through the rules returned from the DirectorySecurity
foreach (AuthorizationRule rule in rules)
{
    //If we find one that matches the identity we are looking for
    if (rule.IdentityReference.Value.Equals(NtAccountName,StringComparison.CurrentCultureIgnoreCase))
    {
        var filesystemAccessRule = (FileSystemAccessRule)rule;

        //Cast to a FileSystemAccessRule to check for access rights
        if ((filesystemAccessRule.FileSystemRights & FileSystemRights.WriteData)>0 && filesystemAccessRule.AccessControlType != AccessControlType.Deny)
        {
            Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path));
        }
        else
        {
            Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path));
        }
    }
}

Console.ReadLine();

将其放入控制台应用程序中,看看它是否满足您的需要。

I appreciate that this is a little late in the day for this post, but you might find this bit of code useful.

string path = @"c:\temp";
string NtAccountName = @"MyDomain\MyUserOrGroup";

DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All);
AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

//Go through the rules returned from the DirectorySecurity
foreach (AuthorizationRule rule in rules)
{
    //If we find one that matches the identity we are looking for
    if (rule.IdentityReference.Value.Equals(NtAccountName,StringComparison.CurrentCultureIgnoreCase))
    {
        var filesystemAccessRule = (FileSystemAccessRule)rule;

        //Cast to a FileSystemAccessRule to check for access rights
        if ((filesystemAccessRule.FileSystemRights & FileSystemRights.WriteData)>0 && filesystemAccessRule.AccessControlType != AccessControlType.Deny)
        {
            Console.WriteLine(string.Format("{0} has write access to {1}", NtAccountName, path));
        }
        else
        {
            Console.WriteLine(string.Format("{0} does not have write access to {1}", NtAccountName, path));
        }
    }
}

Console.ReadLine();

Drop that into a Console app and see if it does what you need.

情域 2024-08-11 15:56:43

这是在 C# 中检查文件夹访问的完全有效的方法。它唯一可能失败的地方是,如果您需要在紧密循环中调用它,其中异常的开销可能是一个问题。

还有其他类似 之前提出的问题

That's a perfectly valid way to check for folder access in C#. The only place it might fall down is if you need to call this in a tight loop where the overhead of an exception may be an issue.

There have been other similar questions asked previously.

眸中客 2024-08-11 15:56:43

我尝试了其中的大部分,但它们给出了误报,都是出于同样的原因。测试目录的可用权限是不够的,您必须检查登录的用户是否是具有该权限的组的成员。为此,您需要获取用户身份,并检查它是否是包含 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;
}

I tried most of these, but they give false positives, all for the same reason. It is not enough to test the directory for an available permission, you have to check that the logged in user is a member of a group that has that permission. To do this you get the users identity, and check if it is a member of a group that contains the FileSystemAccessRule IdentityReference. I have tested this, works flawlessly.

/// <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;
}
凹づ凸ル 2024-08-11 15:56:43

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

IMHO the only 100% reliable way to test if you can write to a directory is to actually write to it and eventually catch exceptions.

神魇的王 2024-08-11 15:56:43

例如,对于所有用户(Builtin\Users),此方法效果很好 - 享受吧。

public static bool HasFolderWritePermission(string destDir)
{
   if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false;
   try
   {
      DirectorySecurity security = Directory.GetAccessControl(destDir);
      SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
      foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
      {
          if(rule.IdentityReference == users)
          {
             FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
             if(rights.AccessControlType == AccessControlType.Allow)
             {
                    if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
             }
          }
       }
       return false;
    }
    catch
    {
        return false;
    }
}

For example for all users (Builtin\Users), this method works fine - enjoy.

public static bool HasFolderWritePermission(string destDir)
{
   if(string.IsNullOrEmpty(destDir) || !Directory.Exists(destDir)) return false;
   try
   {
      DirectorySecurity security = Directory.GetAccessControl(destDir);
      SecurityIdentifier users = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
      foreach(AuthorizationRule rule in security.GetAccessRules(true, true, typeof(SecurityIdentifier)))
      {
          if(rule.IdentityReference == users)
          {
             FileSystemAccessRule rights = ((FileSystemAccessRule)rule);
             if(rights.AccessControlType == AccessControlType.Allow)
             {
                    if(rights.FileSystemRights == (rights.FileSystemRights | FileSystemRights.Modify)) return true;
             }
          }
       }
       return false;
    }
    catch
    {
        return false;
    }
}
终遇你 2024-08-11 15:56:43

上面的解决方案很好,但对我来说,我发现这段代码简单且可行。
只需创建一个临时文件。如果文件被创建,则意味着用户具有写权限。

        public static bool HasWritePermission(string tempfilepath)
        {
            try
            {
                System.IO.File.Create(tempfilepath + "temp.txt").Close();
                System.IO.File.Delete(tempfilepath + "temp.txt");
            }
            catch (System.UnauthorizedAccessException ex)
            {

                return false;
            }

            return true;
        }

Above solutions are good but for me, I find this code simple and workable.
Just create a temporary file. If the file is created, its mean user has the write access.

        public static bool HasWritePermission(string tempfilepath)
        {
            try
            {
                System.IO.File.Create(tempfilepath + "temp.txt").Close();
                System.IO.File.Delete(tempfilepath + "temp.txt");
            }
            catch (System.UnauthorizedAccessException ex)
            {

                return false;
            }

            return true;
        }
我偏爱纯白色 2024-08-11 15:56:43

您的代码获取给定目录的DirectorySecurity,并正确处理异常(由于您无权访问安全信息)。但是,在您的示例中,您实际上并没有询问返回的对象来查看允许哪些访问 - 我认为您需要添加它。

Your code gets the DirectorySecurity for a given directory, and handles an exception (due to your not having access to the security info) correctly. However, in your sample you don't actually interrogate the returned object to see what access is allowed - and I think you need to add this in.

独孤求败 2024-08-11 15:56:43

试试这个:

try
{
    DirectoryInfo di = new DirectoryInfo(path);
    DirectorySecurity acl = di.GetAccessControl();
    AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

    WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(currentUser);
    foreach (AuthorizationRule rule in rules)
    {
        FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
        if (fsAccessRule == null)
            continue;

        if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
        {
            NTAccount ntAccount = rule.IdentityReference as NTAccount;
            if (ntAccount == null)
            {
                continue;
            }

            if (principal.IsInRole(ntAccount.Value))
            {
                Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value);
                continue;
            }
            Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value);                        
        }
    }
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("does not have write access");
}

Try this:

try
{
    DirectoryInfo di = new DirectoryInfo(path);
    DirectorySecurity acl = di.GetAccessControl();
    AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));

    WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(currentUser);
    foreach (AuthorizationRule rule in rules)
    {
        FileSystemAccessRule fsAccessRule = rule as FileSystemAccessRule;
        if (fsAccessRule == null)
            continue;

        if ((fsAccessRule.FileSystemRights & FileSystemRights.WriteData) > 0)
        {
            NTAccount ntAccount = rule.IdentityReference as NTAccount;
            if (ntAccount == null)
            {
                continue;
            }

            if (principal.IsInRole(ntAccount.Value))
            {
                Console.WriteLine("Current user is in role of {0}, has write access", ntAccount.Value);
                continue;
            }
            Console.WriteLine("Current user is not in role of {0}, does not have write access", ntAccount.Value);                        
        }
    }
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("does not have write access");
}
还如梦归 2024-08-11 15:56:43

这是 CsabaS 的答案的修改版本,它考虑了显式拒绝访问规则。该函数遍历目录的所有 FileSystemAccessRules,并检查当前用户是否处于有权访问目录的角色。如果未找到此类角色或用户属于访问被拒绝的角色,则该函数返回 false。要检查读取权限,请将 FileSystemRights.Read 传递给该函数;对于写入权限,请传递 FileSystemRights.Write。如果要检查任意用户的权限而不是当前用户的权限,请将 currentUser WindowsIdentity 替换为所需的 WindowsIdentity。我还建议不要依赖这样的函数来确定用户是否可以安全地使用该目录。 这个答案完美地解释了原因。

    public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights)
    {
        var isInRoleWithAccess = false;

        try
        {
            var di = new DirectoryInfo(path);
            var acl = di.GetAccessControl();
            var rules = acl.GetAccessRules(true, true, typeof(NTAccount));

            var currentUser = WindowsIdentity.GetCurrent();
            var principal = new WindowsPrincipal(currentUser);
            foreach (AuthorizationRule rule in rules)
            {
                var fsAccessRule = rule as FileSystemAccessRule;
                if (fsAccessRule == null)
                    continue;

                if ((fsAccessRule.FileSystemRights & accessRights) > 0)
                {
                    var ntAccount = rule.IdentityReference as NTAccount;
                    if (ntAccount == null)
                        continue;

                    if (principal.IsInRole(ntAccount.Value))
                    {
                        if (fsAccessRule.AccessControlType == AccessControlType.Deny)
                            return false;
                        isInRoleWithAccess = true;
                    }
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
        return isInRoleWithAccess;
    }

Here is a modified version of CsabaS's answer, which accounts for explicit deny access rules. The function goes through all FileSystemAccessRules for a directory, and checks if the current user is in a role which has access to a directory. If no such roles are found or the user is in a role with denied access, the function returns false. To check read rights, pass FileSystemRights.Read to the function; for write rights, pass FileSystemRights.Write. If you want to check an arbitrary user's rights and not the current one's, substitute the currentUser WindowsIdentity for the desired WindowsIdentity. I would also advise against relying on functions like this to determine if the user can safely use the directory. This answer perfectly explains why.

    public static bool UserHasDirectoryAccessRights(string path, FileSystemRights accessRights)
    {
        var isInRoleWithAccess = false;

        try
        {
            var di = new DirectoryInfo(path);
            var acl = di.GetAccessControl();
            var rules = acl.GetAccessRules(true, true, typeof(NTAccount));

            var currentUser = WindowsIdentity.GetCurrent();
            var principal = new WindowsPrincipal(currentUser);
            foreach (AuthorizationRule rule in rules)
            {
                var fsAccessRule = rule as FileSystemAccessRule;
                if (fsAccessRule == null)
                    continue;

                if ((fsAccessRule.FileSystemRights & accessRights) > 0)
                {
                    var ntAccount = rule.IdentityReference as NTAccount;
                    if (ntAccount == null)
                        continue;

                    if (principal.IsInRole(ntAccount.Value))
                    {
                        if (fsAccessRule.AccessControlType == AccessControlType.Deny)
                            return false;
                        isInRoleWithAccess = true;
                    }
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            return false;
        }
        return isInRoleWithAccess;
    }
最丧也最甜 2024-08-11 15:56:43

您可以尝试以下代码块来检查目录是否具有写访问权限。
它检查 FileSystemAccessRule。

string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
bool isWriteAccess = false;
try
{
    AuthorizationRuleCollection collection =
        Directory.GetAccessControl(directoryPath)
            .GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
    foreach (FileSystemAccessRule rule in collection)
    {
        if (rule.AccessControlType == AccessControlType.Allow)
        {
            isWriteAccess = true;
            break;
        }
    }
}
catch (UnauthorizedAccessException ex)
{
    isWriteAccess = false;
}
catch (Exception ex)
{
    isWriteAccess = false;
}
if (!isWriteAccess)
{
    //handle notifications 
}

You can try following code block to check if the directory is having Write Access.
It checks the FileSystemAccessRule.

string directoryPath = "C:\\XYZ"; //folderBrowserDialog.SelectedPath;
bool isWriteAccess = false;
try
{
    AuthorizationRuleCollection collection =
        Directory.GetAccessControl(directoryPath)
            .GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
    foreach (FileSystemAccessRule rule in collection)
    {
        if (rule.AccessControlType == AccessControlType.Allow)
        {
            isWriteAccess = true;
            break;
        }
    }
}
catch (UnauthorizedAccessException ex)
{
    isWriteAccess = false;
}
catch (Exception ex)
{
    isWriteAccess = false;
}
if (!isWriteAccess)
{
    //handle notifications 
}
假面具 2024-08-11 15:56:43

您的代码中存在潜在的竞争条件 - 如果在您检查时用户具有写入文件夹的权限,但在用户实际写入文件夹之前此权限被撤回,会发生什么情况?写入将抛出一个异常,您需要捕获并处理该异常。所以最初的检查是没有意义的。您不妨只进行写入并处理任何异常。这是适合您情况的标准模式。

You have a potential race condition in your code--what happens if the user has permissions to write to the folder when you check, but before the user actually writes to the folder this permission is withdrawn? The write will throw an exception which you will need to catch and handle. So the initial check is pointless. You might as well just do the write and handle any exceptions. This is the standard pattern for your situation.

韵柒 2024-08-11 15:56:43

http://www.codeproject.com/KB/files/UserFileAccessRights.aspx

非常有用的课程,请在下面的消息中检查改进的版本。

http://www.codeproject.com/KB/files/UserFileAccessRights.aspx

Very usefull Class, check for improved version in messages bellow.

↙厌世 2024-08-11 15:56:43

仅仅尝试访问有问题的文件不一定是足够的。测试将使用运行程序的用户的权限运行 - 这不一定是您要测试的用户权限。

Simply trying to access the file in question isn't necessarily enough. The test will run with the permissions of the user running the program - Which isn't necessarily the user permissions you want to test against.

随梦而飞# 2024-08-11 15:56:43

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

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

This should be all you need, as far as I can tell you only need to catch the one exception.

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(
quot;Error accessing file {temp_path}", ex);

        return false;
    }
}
酒废 2024-08-11 15:56:43

我同意阿什的观点,应该没问题。或者,您可以使用声明性 CAS,并在没有访问权限的情况下从一开始就阻止程序运行。

据我所知,我相信 C# 4.0 中可能不存在某些 CAS 功能,不确定这是否是一个问题。

I agree with Ash, that should be fine. Alternatively you could use declarative CAS and actually prevent the program from running in the first place if they don't have access.

I believe some of the CAS features may not be present in C# 4.0 from what I've heard, not sure if that might be an issue or not.

幸福%小乖 2024-08-11 15:56:43

我无法按照接受的答案中的建议让 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;
        }

希望这有帮助。

I couldn't get GetAccessControl() to throw an exception on Windows 7 as recommended in the accepted answer.

I ended up using a variation of sdds's answer:

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

Hope this helps.

Hello爱情风 2024-08-11 15:56:43

我遇到了同样的问题:如何验证我是否可以在特定目录中读/写。我最终找到了一个简单的解决方案......实际测试它。
这是我的简单但有效的解决方案。

 class Program
{

    /// <summary>
    /// Tests if can read files and if any are present
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canRead(string dirPath)
    {
        try
        {
            IEnumerable<string> files = Directory.EnumerateFiles(dirPath);
            if (files.Count().Equals(0))
                return new genericResponse() { status = true, idMsg = genericResponseType.NothingToRead };

            return new genericResponse() { status = true, idMsg = genericResponseType.OK };
        }
        catch (DirectoryNotFoundException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.ItemNotFound };

        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotRead };

        }

    }

    /// <summary>
    /// Tests if can wirte both files or Directory
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canWrite(string dirPath)
    {

        try
        {
            string testDir = "__TESTDIR__";
            Directory.CreateDirectory(string.Join("/", dirPath, testDir));

            Directory.Delete(string.Join("/", dirPath, testDir));


            string testFile = "__TESTFILE__.txt";
            try
            {
                TextWriter tw = new StreamWriter(string.Join("/", dirPath, testFile), false);
                tw.WriteLine(testFile);
                tw.Close();
                File.Delete(string.Join("/", dirPath, testFile));

                return new genericResponse() { status = true, idMsg = genericResponseType.OK };
            }
            catch (UnauthorizedAccessException ex)
            {

                return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteFile };

            }


        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteDir };

        }
    }


}

public class genericResponse
{

    public bool status { get; set; }
    public genericResponseType idMsg { get; set; }
    public string msg { get; set; }

}

public enum genericResponseType
{

    NothingToRead = 1,
    OK = 0,
    CannotRead = -1,
    CannotWriteDir = -2,
    CannotWriteFile = -3,
    ItemNotFound = -4

}

希望有帮助!

I faced the same problem: how to verify if I can read/write in a particular directory. I ended up with the easy solution to...actually test it.
Here is my simple though effective solution.

 class Program
{

    /// <summary>
    /// Tests if can read files and if any are present
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canRead(string dirPath)
    {
        try
        {
            IEnumerable<string> files = Directory.EnumerateFiles(dirPath);
            if (files.Count().Equals(0))
                return new genericResponse() { status = true, idMsg = genericResponseType.NothingToRead };

            return new genericResponse() { status = true, idMsg = genericResponseType.OK };
        }
        catch (DirectoryNotFoundException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.ItemNotFound };

        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotRead };

        }

    }

    /// <summary>
    /// Tests if can wirte both files or Directory
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    private genericResponse check_canWrite(string dirPath)
    {

        try
        {
            string testDir = "__TESTDIR__";
            Directory.CreateDirectory(string.Join("/", dirPath, testDir));

            Directory.Delete(string.Join("/", dirPath, testDir));


            string testFile = "__TESTFILE__.txt";
            try
            {
                TextWriter tw = new StreamWriter(string.Join("/", dirPath, testFile), false);
                tw.WriteLine(testFile);
                tw.Close();
                File.Delete(string.Join("/", dirPath, testFile));

                return new genericResponse() { status = true, idMsg = genericResponseType.OK };
            }
            catch (UnauthorizedAccessException ex)
            {

                return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteFile };

            }


        }
        catch (UnauthorizedAccessException ex)
        {

            return new genericResponse() { status = false, idMsg = genericResponseType.CannotWriteDir };

        }
    }


}

public class genericResponse
{

    public bool status { get; set; }
    public genericResponseType idMsg { get; set; }
    public string msg { get; set; }

}

public enum genericResponseType
{

    NothingToRead = 1,
    OK = 0,
    CannotRead = -1,
    CannotWriteDir = -2,
    CannotWriteFile = -3,
    ItemNotFound = -4

}

Hope it helps !

故人爱我别走 2024-08-11 15:56:43

这里的大多数答案都不会检查写访问权限。它只是检查用户/组是否可以“读取权限”(读取文件/目录的 ACE 列表)。

另外,迭代 ACE 并检查它是否与安全标识符匹配也不起作用,因为用户可能是他可能获得/失去权限的组的成员。比这更糟糕的是嵌套组。

我知道这是一个旧线程,但现在对于任何人来说都有更好的方法。

如果用户具有读取权限,则可以使用 Authz API 来检查有效访问。

https://learn.microsoft.com/en- us/windows/win32/secauthz/using-authz-api

https://learn.microsoft.com/en-us/windows/win32/secauthz/checking-access-with-authz-api

Most of the answers here does not check for write access. It just check if the user/group can 'Read Permission' (Read the ACE list of the file/directory).

Also iterating through ACE and checking if it matches the Security Identifier does not work because the user can be a member of a group from which he might get/lose privilege. Worse than that is nested groups.

I know this is an old thread but there is a better way for any one looking now.

Provided the user has Read Permission privilege is, one can use the Authz API to check Effective access.

https://learn.microsoft.com/en-us/windows/win32/secauthz/using-authz-api

https://learn.microsoft.com/en-us/windows/win32/secauthz/checking-access-with-authz-api

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文