2010-03-15 9 views
4

파일 서버 마이그레이션을 수행하고 있으며 사용자 그룹에 사용자 권한을 매핑 할 수 있도록 작은 C# 응용 프로그램을 작성하고 있습니다. 그것은이 263 문자 파일 경로에 도착하면 실패하지만긴 경로에 대한 보안 세부 정보를 얻으려면 어떻게해야합니까?

나는 현재

Directory.GetAccessControl(path); 

을 사용하고 있습니다.

이름이 잘못되었습니다.
매개 변수 이름 : 작업이 방법을 주위 또는 대안이

내가 DirectoryInfo.GetAccessControl();

를 사용할 때이 같은 오류가 이름을?

감사합니다.

+0

나는 파일 이름에 260 문자 제한을 넘을 방법이 없다고 생각하기 시작했다. 필자는 필요할 때 C#으로 드라이브를 매핑하는 방법을 살펴볼 것입니다. 모두에게 감사드립니다! –

+0

aejw와 그의 드라이브 매핑 라이브러리에 특별히 감사드립니다. http://www.codeproject.com/KB/system/mapnetdrive.aspx –

답변

2

한 가지 대안은 subst을 사용하는 것입니다. 당신의 260 문자 제한에 포함되지 않습니다 드라이브 전체 시작 섹션 : 명령 프롬프트에서, 당신은

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

이 나서 X에서 작업을 수행 할 수 있습니다.

+0

이것은 제가 사용했던 솔루션에 가장 가깝습니다. –

1

라이브러리의 임의의 제한 사항 인 경우 디렉토리에 8 자 이름을 사용해 볼 수 있습니다. 이 이름은/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() –

+0

이상한데, 아마도 System.IO.dll을 디 컴파일해야합니다. 왜/어떻게하는지보십시오. –

2

"확장 길이 경로"를 지정하기 위해 "\? \"경로 앞에 접두어를 붙입니다. Directory.GetAccessControl()`이 확장 길이 경로에서도 작동하는지 테스트 할 수는 없지만 시도 :

최대 경로 길이 제한이 (다음 단락에서 논의 된 몇 가지 예외를 제외하고) 윈도우 API에서

가, 경로의 최대 길이는 MAX_PATH입니다 :

http://msdn.microsoft.com/en-us/library/aa365247.aspx에서 260 자로 정의됩니다. 로컬 경로는 드라이브 문자, 콜론, 백 슬래시, 백 슬래시로 구분 된 이름 구성 요소 및 종료 null 문자 순서로 구성됩니다. 예를 들어, 드라이브 D의 최대 경로는 "D:\<some 256-character path string><NUL>"입니다. 여기서 "<NUL>"은 현재 시스템 코드 페이지의 보이지 않는 종료 널 문자를 나타냅니다. (문자는 < > 시각적 명확성을 위해 여기에 사용되는 유효한 경로 문자열의 일부가 될 수 없습니다.)

참고 파일의 I/윈도우 API에서 O 기능은 NT 스타일에 이름을 변환의 일환으로 "\""/" 변환 이름 (다음 섹션에서 설명하는 것처럼 "\\?\" 접두어를 사용할 때 제외).

Windows API에는 32,767 자의 최대 총 경로 길이에 대해 확장 길이 경로를 허용하는 유니 코드 버전이있는 많은 기능이 있습니다. 이 유형의 경로는 백 슬래시로 구분 된 구성 요소로 구성되며 각 매개 변수는 GetVolumeInformation 함수의 lpMaximumComponentLength 매개 변수에 반환되는 값까지 있습니다 (이 값은 일반적으로 255 자입니다). 확장 길이 경로를 지정하려면 "\\?\" 접두어를 사용하십시오. 예 : "\\?\D:\<very long path>". 문자 < >은 시각적 인 명확성을 위해 여기에 사용되며 유효한 경로 문자열의 일부가 될 수 없습니다.

+0

흠, 잘 작동하지 않는 것 같습니다. (생각을 고맙게 생각합니다. –

1

위에서 언급 한 라이브러리를 사용하면 트릭을 멋지게 수행 할 수 있습니다. 필자는 필자가 필요에 따라 더 많은 매핑 된 드라이브 문자를 붙잡아 야한다고 생각하지만 최대 dir 길이는 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; 
      } 
     } 
    } 
} 
관련 문제