如何获得长途径的安全细节?

我正在做一个文件服务器迁移,我正在写一个小的C#应用​​程序来帮助我映射用户权限,以便我们可以把它们放在用户组中。

我目前正在使用

Directory.GetAccessControl(path); 

然而,它到达这个263 char文件path时失败。

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

我使用DirectoryInfo.GetAccessControl();时得到相同的错误DirectoryInfo.GetAccessControl();

有没有解决方法或替代这种方法?

谢谢!

Solutions Collecting From Web of "如何获得长途径的安全细节?"

一种替代方法是使用subst 。 从命令提示符处,您可以执行

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

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

用“\?\”前缀路径来指定一个“扩展路径”。我还没有能够测试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>" 。 (字符< >在这里用于视觉清晰,不能是有效路径字符串的一部分。)

如果它是库中的任意限制,那么可以尝试使用目录的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 

简短的名字是那些带有撇号的。尝试将这些传递给函数来减少字符串的长度。 没有保证,这将工作,介意。

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

使用上面提到的库,这个技巧很好。 我想我应该抓住更多的映射驱动器字母,但我的最大长度只有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; } } } }