2010-02-20 19 views
7

Trong .NET, tôi nghĩ rằng tôi có thể xác định nếu một tập tin là một liên kết tượng trưng bằng cách gọi System.IO.File.GetAttributes(), và kiểm tra bit ReparsePoint. như vậy:Trong .NET, Làm thế nào để có được đích của một liên kết tượng trưng (hoặc Điểm tái tạo)?

var a = System.IO.File.GetAttributes(fileName); 
if ((a & FileAttributes.ReparsePoint) != 0) 
{ 
    // it's a symlink 
} 

Làm cách nào để có được mục tiêu của liên kết tượng trưng?


ps: Tôi biết làm thế nào để tạo một liên kết tượng trưng. Yêu cầu P/Invoke:

[Interop.DllImport("kernel32.dll", EntryPoint="CreateSymbolicLinkW", CharSet=Interop.CharSet.Unicode)] 
public static extern int CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); 

Trả lời

7

Bạn phải sử dụng DeviceIoControl() và gửi mã kiểm soát FSCTL_GET_REPARSE_POINT. Các chi tiết sử dụng P/Invoke và API khá gớm ghiếc, nhưng nó là Googles really well.

+1

này dẫn tôi đến mã nguồn cho Powershell Community Extensions (PSCX), mã có mã tốt để xử lý ReparsePoints. – Cheeso

4

Open the file và sau đó vượt qua tay cầm đến GetFinalPathNameByHandle.

+0

hoạt động với Vista hoặc tốt hơn hoặc WS2008 trở lên. – Cheeso

+1

@Cheeso: các liên kết tượng trưng đến các tệp được khởi chạy trong Vista, AFAIK. Vì vậy, tất cả các tập tin flinkins dựa trên symlink sẽ có cùng hạn chế đó. –

+2

Điểm khan hiếm đã có từ Win2k; nó chỉ là các liên kết tượng trưng cho các tệp được khởi chạy trong Vista. – Gabe

8

Dựa trên những câu trả lời mà đề cập GetFinalPathNameByHandle đây là mã C# mà thực hiện điều này (vì tất cả các câu trả lời khác chỉ là con trỏ):

Cách sử dụng

var path = NativeMethods.GetFinalPathName(@"c:\link"); 

Code:

public static class NativeMethods 
{ 
    private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); 

    private const uint FILE_READ_EA = 0x0008; 
    private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000; 

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool CloseHandle(IntPtr hObject); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern IntPtr CreateFile(
      [MarshalAs(UnmanagedType.LPTStr)] string filename, 
      [MarshalAs(UnmanagedType.U4)] uint access, 
      [MarshalAs(UnmanagedType.U4)] FileShare share, 
      IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero 
      [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, 
      [MarshalAs(UnmanagedType.U4)] uint flagsAndAttributes, 
      IntPtr templateFile); 

    public static string GetFinalPathName(string path) 
    { 
     var h = CreateFile(path, 
      FILE_READ_EA, 
      FileShare.ReadWrite | FileShare.Delete, 
      IntPtr.Zero, 
      FileMode.Open, 
      FILE_FLAG_BACKUP_SEMANTICS, 
      IntPtr.Zero); 
     if (h == INVALID_HANDLE_VALUE) 
      throw new Win32Exception(); 

     try 
     { 
      var sb = new StringBuilder(1024); 
      var res = GetFinalPathNameByHandle(h, sb, 1024, 0); 
      if (res == 0) 
       throw new Win32Exception(); 

      return sb.ToString(); 
     } 
     finally 
     { 
      CloseHandle(h); 
     } 
    } 
} 
+0

Tôi nghĩ (nhưng tôi chưa thử nghiệm) nhưng bạn có thể đơn giản hóa mã của bạn bằng cách sử dụng đối tượng NET FileStream sau đó sử dụng 'var h = yourStream.SafeFileHandle.DangerousGetHandle()', khi bạn đóng luồng, bạn cũng giải phóng xử lý vì vậy bạn không cần phải gọi 'CloseHandle (h)' trên biến đó. Bạn thậm chí có thể làm cho hàm nhận trong một 'FileStream' thay vì một chuỗi. –

+1

@ScottChamberlain - lý do tại sao tôi không sử dụng FileStream là a) Tôi không chắc liệu nó có đi qua các thuộc tính không được định nghĩa trong .NET và b) Tôi không chắc liệu nó có làm việc cho các thư mục hay không (CreateFile) làm việc). Plus này nên được nhanh hơn (mặc dù tôi đã không đo nó). –

+0

Nếu bạn thích tôi, điều tiếp theo bạn sẽ muốn biết là: https://stackoverflow.com/questions/31439011/getfinalpathnamebyhandle-without-prepended – datguy

Các vấn đề liên quan