2010-03-15 47 views
4

我正在做一個文件服務器遷移,我正在寫一個小的C#應用​​程序來幫助我映射用戶權限,以便我們可以將它們放入用戶組中。如何獲得長路徑的安全細節?

我目前使用

Directory.GetAccessControl(path); 

然而,當它到達這個263字符的文件路徑失敗。

名稱無效。
參數名:名

我得到同樣的錯誤,當我使用DirectoryInfo.GetAccessControl();

是否有變通或替代這種方法嗎?

謝謝!

+0

我開始認爲沒有辦法超過文件名上的260個字符限制。我將在需要時使用C#將映射驅動器映射到該位置。感謝大家! – 2010-03-15 23:08:19

+0

特別感謝aejw和他的驅動器映射庫。 http://www.codeproject.com/KB/system/mapnetdrive.aspx – 2010-03-19 16:19:11

回答

2

一種替代方案是使用subst。在命令提示符下,可以執行

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

那麼X上執行的操作:驅動器和整個起始段將不會計入260個字符限制。

+0

這是最接近我使用的解決方案:) – 2010-03-19 16:17:12

1

如果它是庫中的任意限制,那麼你可以嘗試使用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 

短名稱是那些在顎化嘗試通過這些的功能,以減少字符串的長度。沒有保證,這將工作,介意。

1

您應該使用DirectoryInfo遞歸處理目錄樹 - 這樣做可以避免傳遞完整路徑。

+0

我試過了,當我執行調用時出現錯誤DirectoryInfo.GetAccessControl() – 2010-03-15 22:15:21

+0

這很奇怪,也許我應該反編譯System.IO.dll到看看爲什麼/如何做到這一點。 – 2010-03-15 22:57:48

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>"表示當前系統代碼頁的不可見的終止空字符。 (字符< >這裏用於視覺清晰度,並不能有效的路徑字符串的一部分。)

Note文件I/Windows API中O功能轉換"/""\"作爲名稱轉換爲NT風格的一部分名稱,但使用"\\?\"前綴時除外,如以下各節所述。

Windows API有許多功能,它們也有Unicode版本以允許擴展長度路徑的最大總路徑長度爲32,767個字符。此類路徑由用反斜槓分隔的組件組成,每個組件由GetVolumeInformation函數的lpMaximumComponentLength參數(該值通常爲255個字符)中返回的值組成。要指定擴展長度路徑,請使用"\\?\"前綴。例如,"\\?\D:\<very long path>"。 (字符< >在這裏用於視覺清晰,不能作爲有效路徑字符串的一部分。)

+0

嗯,似乎無法得到它的工作:(謝謝你的想法,但。 – 2010-03-15 22:55:41

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; 
      } 
     } 
    } 
} 
相關問題