【问题标题】:How do I get the security details for a long path?如何获取长路径的安全详细信息?
【发布时间】:2010-03-15 21:24:19
【问题描述】:

我正在进行文件服务器迁移,并且正在编写一个小型 C# 应用程序来帮助我映射用户权限,以便我们可以将它们放入用户组中。

我正在使用

Directory.GetAccessControl(path);

但是当它到达这个 263 字符文件路径时它失败了。

名称无效。
参数名称:名称

我在使用DirectoryInfo.GetAccessControl();时遇到同样的错误

此方法是否有解决方法或替代方法?

谢谢!

【问题讨论】:

  • 我开始认为文件名不能超过 260 个字符的限制。当我需要它时,我将研究使用 C# 将驱动器映射到该位置。谢谢大家!
  • 特别感谢 aejw 和他的驱动器映射库。 codeproject.com/KB/system/mapnetdrive.aspx

标签: c# windows folder-security


【解决方案1】:

另一种方法是使用subst。在命令提示符下,您可以执行

subst X: "D:\really really really\long path\that you can shorten"

然后在 X: 驱动器上执行您的操作,整个开始部分将不计入您的 260 字符限制。

【讨论】:

  • 这是最接近我使用的解决方案:)
【解决方案2】:

在路径前加上“\?\”以指定“扩展长度路径”。我无法测试 Directory.GetAccessControl()` 是否适用于扩展长度路径,但值得一试:

来自http://msdn.microsoft.com/en-us/library/aa365247.aspx

最大路径长度限制

在 Windows API(以下段落中讨论的一些例外情况)中,路径的最大长度为 MAX_PATH,定义为 260 个字符。本地路径按以下顺序构造:驱动器号、冒号、反斜杠、由反斜杠分隔的名称组件和终止空字符。例如,驱动器 D 上的最大路径是 "D:\<some 256-character path string><NUL>",其中 "<NUL>" 表示当前系统代码页的不可见终止空字符。 (这里使用字符< > 是为了视觉清晰,不能作为有效路径字符串的一部分。)

注意 Windows API 中的文件 I/O 函数将 "/" 转换为 "\",作为将名称转换为 NT 样式名称的一部分,除非使用 "\\?\" 前缀,如以下部分所述。

Windows API 有许多函数也有 Unicode 版本,以允许最大总路径长度为 32,767 个字符的扩展长度路径。这种类型的路径由用反斜杠分隔的组件组成,每个组件的最大长度为 GetVolumeInformation 函数的 lpMaximumComponentLength 参数中返回的值(该值通常为 255 个字符)。要指定扩展长度的路径,请使用 "\\?\" 前缀。例如,"\\?\D:\<very long path>"。 (这里使用字符< > 是为了视觉清晰,不能作为有效路径字符串的一部分。)

【讨论】:

  • 嗯,似乎无法让它工作:(不过谢谢你的想法。
【解决方案3】:

如果它是库中的任意限制,那么您可以尝试使用 8 个字符的目录名称。要确定这些名称是什么,请使用 /X 选项运行 dir:


C:\>dir /x

29/12/2009  23:33              PROGRA~1     Program Files
23/02/2010  21:26              PROGRA~2     Program Files (x86
05/12/2009  20:57                           Users
02/02/2010  09:23                           Windows

短名称是带有波浪线的名称。尝试将它们传递给函数以减少字符串长度。请注意,不保证这会起作用。

【讨论】:

    【解决方案4】:

    您应该使用 DirectoryInfo 递归处理您的目录树 - 这样做可以避免传递完整路径。

    【讨论】:

    • 我试过了,执行调用DirectoryInfo.GetAccessControl()时出现错误
    • 这很奇怪,也许我应该反编译 System.IO.dll 看看它为什么/如何做到这一点。
    【解决方案5】:

    使用我上面提到的库可以很好地解决问题。我想我应该根据需要获取更多映射的驱动器号,但我的最大目录长度只有 300 个字符。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Security;
    using System.Security.AccessControl;
    using aejw.Network;
    
    namespace SecurityScanner
    {
        class Program
        {
            static void Main(string[] args)
            {
                string path = @"\\mynetworkdir";
                DirectoryInfo di = new DirectoryInfo(path);
                List<DirSec> dirs = new List<DirSec>();
                RecordSecurityData(di, dirs, path, path);
    
                //Grouping up my users
                List<List<DirSec>> groups = new List<List<DirSec>>();
                foreach (DirSec d in dirs)
                {
                    bool IsNew = true;
                    foreach (List<DirSec> group in groups)
                    {
                        if (d.IsSameUserList(group[0]))
                        {
                            group.Add(d);
                            IsNew = false;
                            break;
                        }
                    }
                    if (IsNew)
                    {
                        List<DirSec> newGroup = new List<DirSec>();
                        newGroup.Add(d);
                        groups.Add(newGroup);
                    }
                }
    
                //Outputting my potential user groups
                StringBuilder sb = new StringBuilder();
                foreach (List<DirSec> group in groups)
                {
                    foreach (DirSec d in group)
                    {
                        sb.AppendLine(d.DirectoryName);
                    }
                    foreach (string s in group[0].UserList)
                    {
                        sb.AppendLine("\t" + s);
                    }
                    sb.AppendLine();
                }
                File.WriteAllText(@"c:\security.txt", sb.ToString());
            }
    
            public static void RecordSecurityData(DirectoryInfo di, List<DirSec> dirs, string path, string fullPath)
            {
                DirSec me = new DirSec(fullPath);
                DirectorySecurity ds;
                NetworkDrive nd = null;
                if(path.Length <= 248)
                    ds = Directory.GetAccessControl(path);
                else
                {
                    nd = new NetworkDrive();
                    nd.LocalDrive = "X:";
                    nd.ShareName = path;
                    nd.MapDrive();
                    path = @"X:\";
                    di = new DirectoryInfo(path);
                    ds = Directory.GetAccessControl(path);
                }
                foreach (AuthorizationRule ar in ds.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
                {
                    me.AddUser(ar.IdentityReference.Value);
                }
                dirs.Add(me);
                foreach (DirectoryInfo child in di.GetDirectories())
                {
                    RecordSecurityData(child, dirs, path + @"\" + child.Name, fullPath + @"\" + child.Name);
                }
                if (nd != null)
                    nd.UnMapDrive();
            }
    
            public struct DirSec
            {
                public string DirectoryName;
                public List<string> UserList;
    
                public DirSec(string directoryName)
                {
                    DirectoryName = directoryName;
                    UserList = new List<string>();
                }
    
                public void AddUser(string UserName)
                {
                    UserList.Add(UserName);
                }
    
                public bool IsSameUserList(DirSec other)
                {
                    bool isSame = false;
                    if (this.UserList.Count == other.UserList.Count)
                    {
                        isSame = true;
                        foreach (string myUser in this.UserList)
                        {
                            if (!other.UserList.Contains(myUser))
                            {
                                isSame = false;
                                break;
                            }
                        }
                    }
                    return isSame;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-26
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多