我正在做一個文件服務器遷移,我正在寫一個小的C#應用程序來幫助我映射用戶權限,以便我們可以將它們放入用戶組中。如何獲得長路徑的安全細節?
我目前使用
Directory.GetAccessControl(path);
然而,當它到達這個263字符的文件路徑失敗。
名稱無效。
參數名:名
我得到同樣的錯誤,當我使用DirectoryInfo.GetAccessControl();
是否有變通或替代這種方法嗎?
謝謝!
我正在做一個文件服務器遷移,我正在寫一個小的C#應用程序來幫助我映射用戶權限,以便我們可以將它們放入用戶組中。如何獲得長路徑的安全細節?
我目前使用
Directory.GetAccessControl(path);
然而,當它到達這個263字符的文件路徑失敗。
名稱無效。
參數名:名
我得到同樣的錯誤,當我使用DirectoryInfo.GetAccessControl();
是否有變通或替代這種方法嗎?
謝謝!
一種替代方案是使用subst
。在命令提示符下,可以執行
subst X: "D:\really really really\long path\that you can shorten"
那麼X上執行的操作:驅動器和整個起始段將不會計入260個字符限制。
這是最接近我使用的解決方案:) – 2010-03-19 16:17:12
如果它是庫中的任意限制,那麼你可以嘗試使用8個字符名稱作爲目錄。要制定出什麼這些名稱,運行DIR與/ X選項:
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遞歸處理目錄樹 - 這樣做可以避免傳遞完整路徑。
我試過了,當我執行調用時出現錯誤DirectoryInfo.GetAccessControl() – 2010-03-15 22:15:21
這很奇怪,也許我應該反編譯System.IO.dll到看看爲什麼/如何做到這一點。 – 2010-03-15 22:57:48
用「\?\」前綴來指定一個「擴展長度路徑」。我還沒有能夠測試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>"
表示當前系統代碼頁的不可見的終止空字符。 (字符< >
這裏用於視覺清晰度,並不能有效的路徑字符串的一部分。)Note文件I/Windows API中O功能轉換
"/"
到"\"
作爲名稱轉換爲NT風格的一部分名稱,但使用"\\?\"
前綴時除外,如以下各節所述。Windows API有許多功能,它們也有Unicode版本以允許擴展長度路徑的最大總路徑長度爲32,767個字符。此類路徑由用反斜槓分隔的組件組成,每個組件由GetVolumeInformation函數的lpMaximumComponentLength參數(該值通常爲255個字符)中返回的值組成。要指定擴展長度路徑,請使用
"\\?\"
前綴。例如,"\\?\D:\<very long path>"
。 (字符< >
在這裏用於視覺清晰,不能作爲有效路徑字符串的一部分。)
嗯,似乎無法得到它的工作:(謝謝你的想法,但。 – 2010-03-15 22:55:41
使用上面提到的庫很好地實現了這個技巧。我想我應該根據需要抓取更多映射的驅動器盤符,但是我的最大目錄長度只有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;
}
}
}
}
我開始認爲沒有辦法超過文件名上的260個字符限制。我將在需要時使用C#將映射驅動器映射到該位置。感謝大家! – 2010-03-15 23:08:19
特別感謝aejw和他的驅動器映射庫。 http://www.codeproject.com/KB/system/mapnetdrive.aspx – 2010-03-19 16:19:11