我正在进行文件服务器迁移,我正在编写一个小型C#应用程序来帮助我映射用户权限,以便我们将它们放在用户组中。
我正在使用
Directory.GetAccessControl(path);
但是当它到达这个263 char文件路径时它会失败。
名称无效。
参数名称:名称
使用DirectoryInfo.GetAccessControl();
是否有解决方法或替代此方法?
谢谢!
答案 0 :(得分:2)
另一种方法是使用subst
。在命令提示符下,您可以执行
subst X: "D:\really really really\long path\that you can shorten"
然后在X:驱动器上执行操作,整个开始部分将不计入260-char限制。
答案 1 :(得分: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>"
。 (此处使用字符< >
是为了清晰可见,并且不能成为有效路径字符串的一部分。)
答案 2 :(得分:1)
如果它是库中的任意限制,那么您可以尝试使用目录的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
短名称是具有波浪号的那些。尝试将这些名称传递给函数以减少字符串长度。请注意,不保证这会有效。
答案 3 :(得分:1)
您应该使用DirectoryInfo以递归方式处理目录树 - 这样做会避免传递完整路径。
答案 4 :(得分:1)
使用我上面提到的库,这很有效。我想我应该根据需要抓取更多的映射驱动器号,但我的最大目录长度只有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;
}
}
}
}