2013-06-04 45 views
13

Trong PowerShell, tôi cần giải quyết đường dẫn đích của đường giao nhau (liên kết tượng trưng).powershell để giải quyết đường dẫn đích đường giao nhau

ví dụ, nói rằng tôi có một ngã ba c:\someJunction mà mục tiêu là c:\temp\target

tôi đã cố gắng biến thể của $junc = Get-Item c:\someJunction, nhưng chỉ có thể nhận được c:\someJunction

Làm thế nào để tìm ra con đường mục tiêu của đường giao nhau, trong ví dụ này c:\temp\target, của một ngã ba nhất định?

Trả lời

2

Bạn có thể có được con đường bằng cách làm như sau:

Get-ChildItem -Path C:\someJunction 

Chỉnh sửa cho việc tìm kiếm con đường và không phải là nội dung của thư mục

Add-Type -MemberDefinition @" 
private const int FILE_SHARE_READ = 1; 
private const int FILE_SHARE_WRITE = 2; 

private const int CREATION_DISPOSITION_OPEN_EXISTING = 3; 
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; 

[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags); 

[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, 
IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); 

public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink) 
{ 
    SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero); 
    if(directoryHandle.IsInvalid) 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 

    StringBuilder path = new StringBuilder(512); 
    int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0); 
    if (size<0) 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 
    // The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with "\\?\" 
    // More information about "\\?\" here -> http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx 
    if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\') 
    return path.ToString().Substring(4); 
    else 
    return path.ToString(); 
} 
"@ -Name Win32 -NameSpace System -UsingNamespace System.Text,Microsoft.Win32.SafeHandles,System.ComponentModel 

$dir = Get-Item D:\1 
[System.Win32]::GetSymbolicLinkTarget($dir) 
+0

[này trông giống như điều tương tự.] (Http://techibee.com/powershell/read-target-folder-of-a-symlink-using-powershell/1916) –

+0

@BobLobLaw Trên thực tế đã nhận nó từ http://chrisbensen.blogspot.ru/2010/06/getfinalpathnamebyhandle.html – Josh

+0

Cảm ơn, nó đã hoạt động!Tôi cảm thấy rằng tôi phải phàn nàn về những nỗ lực cần thiết để có được một cái gì đó đơn giản như một mục tiêu của ngã ba, nhưng đó không phải là lỗi của bạn ... thịt bò của tôi với sức mạnh. – ash

2

này hiện các trick với công việc ít hơn, và hoạt động ngay cả đối với các nút giao trên máy chủ từ xa:

fsutil reparsepoint query "M:\Junc" 

Nếu bạn muốn chỉ tên đích:

fsutil reparsepoint query "M:\Junc" | where-object { $_ -imatch 'Print Name:' } | foreach-object { $_ -replace 'Print Name\:\s*','' } 

nên

function Get_JunctionTarget($p_path) 
{ 
    fsutil reparsepoint query $p_path | where-object { $_ -imatch 'Print Name:' } | foreach-object { $_ -replace 'Print Name\:\s*','' } 
} 

Ngoài ra, các mã dưới đây là một sửa đổi nhỏ của mã mà Josh cung cấp ở trên. Nó có thể được đặt trong một tập tin được đọc nhiều lần, và nó xử lý hàng đầu \\?\ một cách chính xác trong trường hợp của một ổ đĩa mạng:

function Global:Get_UNCPath($l_dir) 
{ 
    if((([System.Management.Automation.PSTypeName]'System.Win32').Type -eq $null) -or ([system.win32].getmethod('GetSymbolicLinkTarget') -eq $null)) 
    { 
     Add-Type -MemberDefinition @" 
private const int CREATION_DISPOSITION_OPEN_EXISTING = 3; 
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; 

[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags); 

[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)] 
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, 
IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); 

public static string GetSymbolicLinkTarget(System.IO.DirectoryInfo symlink) 
{ 
    SafeFileHandle directoryHandle = CreateFile(symlink.FullName, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero); 
    if(directoryHandle.IsInvalid) 
    { 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 
    } 
    StringBuilder path = new StringBuilder(512); 
    int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0); 
    if (size<0) 
    { 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 
    } 
    // The remarks section of GetFinalPathNameByHandle mentions the return being prefixed with "\\?\" 
    // More information about "\\?\" here -> http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx 
    string sPath = path.ToString(); 
    if(sPath.Length>8 && sPath.Substring(0,8) == @"\\?\UNC\") 
    { 
     return @"\" + sPath.Substring(7); 
    } 
    else if(sPath.Length>4 && sPath.Substring(0,4) == @"\\?\") 
    { 
     return sPath.Substring(4); 
    } 
    else 
    { 
     return sPath; 
    } 
} 
"@ -Name Win32 -NameSpace System -UsingNamespace System.Text,Microsoft.Win32.SafeHandles,System.ComponentModel 
    } 
    [System.Win32]::GetSymbolicLinkTarget($l_dir) 
} 

và đưa ra các chức năng Get_UNCPath trên, chúng ta có thể cải thiện chức năng Get_JunctionTarget như sau :

function Global:Get_JunctionTarget([string]$p_path) 
{ 
    $l_target = fsutil reparsepoint query $p_path | where-object { $_ -imatch 'Print Name\:' } | foreach-object { $_ -replace 'Print Name\:\s*','' } 
    if($l_target -imatch "(^[A-Z])\:\\") 
    { 
     $l_drive = $matches[1] 
     $l_uncPath = Get_UncPath $p_path 
     if($l_uncPath -imatch "(^\\\\[^\\]*\\)") 
     { 
      $l_machine = $matches[1] 
      $l_target = $l_target -replace "^$l_drive\:","$l_machine$l_drive$" 
     } 
    } 
    $l_target 
} 
+0

Cảm ơn ... lệnh đầu tiên đã làm việc rất tốt cho tôi. Nó chỉ mất một chút thời gian để nhận ra đầu ra bao gồm các byte hex của đường dẫn ... cũng như đường dẫn ascii (bên phải). – Xantix

2

Chúng tôi sẽ chỉ sử dụng chức năng này

function Get-SymlinkTargetDirectory {   
    [cmdletbinding()] 
    param(
     [string]$SymlinkDir 
    ) 
    $basePath = Split-Path $SymlinkDir 
    $folder = Split-Path -leaf $SymlinkDir 
    $dir = cmd /c dir /a:l $basePath | Select-String $folder 
    $dir = $dir -join ' ' 
    $regx = $folder + '\ *\[(.*?)\]' 
    $Matches = $null 
    $found = $dir -match $regx 
    if ($found) { 
     if ($Matches[1]) { 
      Return $Matches[1] 
     } 
    } 
    Return '' 
} 
+1

Chỉ giải pháp cho các điểm hệ thống hoàn nguyên như 'C: \ Users \ Joe \ SendTo' afaict – Frank

13

Mục mới, Xóa mục và Get-ChildItem đã được cải tiến để hỗ trợ tạo và quản lý các liên kết tượng trưng. Tham số -ItemType cho New-Item chấp nhận một giá trị mới, SymbolicLink. Bây giờ bạn có thể tạo các liên kết tượng trưng trong một dòng đơn bằng cách chạy lệnh ghép ngắn New-Item.

What's New in Windows PowerShell

Tôi đã kiểm tra sự hỗ trợ liên kết tượng trưng trên máy tính Windows 7 của tôi, nó hoạt động tốt.

> New-Item -Type SymbolicLink -Target C: -Name TestSymlink 


    Directory: C:\Users\skokhanovskiy\Desktop 


Mode    LastWriteTime   Length Name 
----    -------------   ------ ---- 
d----l  06.09.2016  18:27    TestSymlink 

Lấy mục tiêu của liên kết tượng trưng dễ dàng tạo ra.

> Get-Item .\TestSymlink | Select-Object -ExpandProperty Target 
C:\ 
+0

Huh. Cám ơn vì cái này. Tôi sẽ phải điều tra. –

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