2013-06-04 12 views
13

In PowerShell, è necessario risolvere il percorso target di una giunzione (collegamento simbolico).powershell per risolvere il percorso target della giunzione

per esempio, dire che ho un incrocio c:\someJunction il cui obiettivo è c:\temp\target

Ho provato varianti di $junc = Get-Item c:\someJunction, ma era in grado di ottenere c:\someJunction

Come faccio a trovare il percorso di destinazione della giunzione unica, in questo esempio c:\temp\target, di un dato nodo?

risposta

2

è possibile ottenere il percorso nel modo seguente:

Get-ChildItem -Path C:\someJunction 

Edit per trovare il percorso e non il contenuto della cartella

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

[Questo appare come la stessa cosa.] (Http://techibee.com/powershell/read-target-folder-of-a-symlink-using-powershell/1916) –

+0

@BobLobLaw realtà ottenuto da http://chrisbensen.blogspot.ru/2010/06/getfinalpathnamebyhandle.html – Josh

+0

Grazie, ha funzionato!Sento che devo lamentarmi dello sforzo richiesto per ottenere qualcosa di semplice come la dir target di un incrocio, ma non è colpa tua ... il mio manzo è con PowerShell. – ash

2

Questo fa il trucco con meno lavoro, e funziona anche per i nodi su un server remoto:

fsutil reparsepoint query "M:\Junc" 

Se si desidera solo il nome di destinazione:

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

così

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

Inoltre, il codice qui sotto è una leggera modifica del codice che Josh fornito sopra. Può essere messo in un file che viene letto più volte, e gestisce il principale \\?\ correttamente nel caso di un'unità di rete:

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) 
} 

e dato al di sopra della funzione di Get_UNCPath, siamo in grado di migliorare la funzione Get_JunctionTarget come segue :

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

Grazie ... il primo comando ha funzionato molto bene per me. Ci è voluto solo un attimo per capire che l'output includeva i byte esadecimali del percorso ... così come il percorso degli ascii (sulla destra). – Xantix

2

Si finisce per utilizzare questa funzione

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

Solo soluzione per i punti di analisi del sistema come "C: \ Users \ Joe \ SendTo" afaict – Frank

13

New-Item, Remove-Item e Get-ChildItem sono stati migliorati per supportare la creazione e la gestione dei collegamenti simbolici. Il parametro -ItemType per New-Item accetta un nuovo valore, SymbolicLink. Ora è possibile creare collegamenti simbolici in una singola riga eseguendo il cmdlet New-Item.

What's New in Windows PowerShell

Ho controllato il supporto link simbolico sulla mia macchina Windows 7, è funziona bene.

> 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 

Ottenere il target del collegamento simbolico facile come crearlo.

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

Huh. Grazie per questo. Dovrò indagare. –

Problemi correlati