Search code examples
powershellsymlinkjunction

powershell to resolve junction target path


In PowerShell, I need resolve the target path of a junction (symlink).

for example, say I have a junction c:\someJunction whose target is c:\temp\target

I tried variations of $junc = Get-Item c:\someJunction, but was only able to get c:\someJunction

How do I find the target path of the junction, in this example c:\temp\target, of a given junction?


Solution

  • You can get the path by doing the following:

    Get-ChildItem -Path C:\someJunction
    

    Edit for finding the path and not the contents of the folder

    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)