powershell to resolve junction target path

后端 未结 7 1124
闹比i
闹比i 2020-12-09 15:32

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:\\te

7条回答
  •  我在风中等你
    2020-12-09 15:58

    It seems that with PS5 (as mentioned here or somewhere else?), system-defined junctions/reparse points have a bug whereas symlinks and user-defined junctions/reparse points do not. These solutions seem to work for symlinks but not junctions. The only thing that I could get to work to show the proper info was the fsutil program. The only issue is that it outputs data similar to Format-Hex as shown below.

    The fsutil tool give me this output when used with the Windows Store app stored in $path

    PS C:\> $path = "$($env:USERPROFILE)\AppData\Local\Microsoft\WindowsApps\Skype.exe"
    PS C:\> fsutil reparsepoint query $path
    Reparse Data Length: 0x150
    Reparse Data:
    0000:  03 00 00 00 4d 00 69 00  63 00 72 00 6f 00 73 00  ....M.i.c.r.o.s.
    0010:  6f 00 66 00 74 00 2e 00  53 00 6b 00 79 00 70 00  o.f.t...S.k.y.p.
    0020:  65 00 41 00 70 00 70 00  5f 00 6b 00 7a 00 66 00  e.A.p.p._.k.z.f.
    0030:  38 00 71 00 78 00 66 00  33 00 38 00 7a 00 67 00  8.q.x.f.3.8.z.g.
    0040:  35 00 63 00 00 00 4d 00  69 00 63 00 72 00 6f 00  5.c...M.i.c.r.o.
    0050:  73 00 6f 00 66 00 74 00  2e 00 53 00 6b 00 79 00  s.o.f.t...S.k.y.
    0060:  70 00 65 00 41 00 70 00  70 00 5f 00 6b 00 7a 00  p.e.A.p.p._.k.z.
    0070:  66 00 38 00 71 00 78 00  66 00 33 00 38 00 7a 00  f.8.q.x.f.3.8.z.
    0080:  67 00 35 00 63 00 21 00  41 00 70 00 70 00 00 00  g.5.c.!.A.p.p...
    0090:  43 00 3a 00 5c 00 50 00  72 00 6f 00 67 00 72 00  C.:.\.P.r.o.g.r.
    00a0:  61 00 6d 00 20 00 46 00  69 00 6c 00 65 00 73 00  a.m. .F.i.l.e.s.
    00b0:  5c 00 57 00 69 00 6e 00  64 00 6f 00 77 00 73 00  \.W.i.n.d.o.w.s.
    00c0:  41 00 70 00 70 00 73 00  5c 00 4d 00 69 00 63 00  A.p.p.s.\.M.i.c.
    00d0:  72 00 6f 00 73 00 6f 00  66 00 74 00 2e 00 53 00  r.o.s.o.f.t...S.
    00e0:  6b 00 79 00 70 00 65 00  41 00 70 00 70 00 5f 00  k.y.p.e.A.p.p._.
    00f0:  31 00 35 00 2e 00 36 00  34 00 2e 00 38 00 30 00  1.5...6.4...8.0.
    0100:  2e 00 30 00 5f 00 78 00  38 00 36 00 5f 00 5f 00  ..0._.x.8.6._._.
    0110:  6b 00 7a 00 66 00 38 00  71 00 78 00 66 00 33 00  k.z.f.8.q.x.f.3.
    0120:  38 00 7a 00 67 00 35 00  63 00 5c 00 53 00 6b 00  8.z.g.5.c.\.S.k.
    0130:  79 00 70 00 65 00 5c 00  53 00 6b 00 79 00 70 00  y.p.e.\.S.k.y.p.
    0140:  65 00 2e 00 65 00 78 00  65 00 00 00 30 00 00 00  e...e.x.e...0...
    
    OR
    
    PS C:\> $path2 = "$HOME/My Documents"
    PS C:\> fsutil reparsepoint query $path2
    Reparse Tag Value : 0xa0000003
    Tag value: Microsoft
    Tag value: Name Surrogate
    Tag value: Mount Point
    Substitue Name offset: 0
    Substitue Name length: 56
    Print Name offset:     58
    Print Name Length:     48
    Substitute Name:       \??\C:\Users\chefh\Documents
    Print Name:            C:\Users\chefh\Documents
    
    Reparse Data Length: 0x74      
    Reparse Data:
    0000:  00 00 38 00 3a 00 30 00  5c 00 3f 00 3f 00 5c 00  ..8.:.0.\.?.?.\.
    0010:  43 00 3a 00 5c 00 55 00  73 00 65 00 72 00 73 00  C.:.\.U.s.e.r.s.
    0020:  5c 00 63 00 68 00 65 00  66 00 68 00 5c 00 44 00  \.c.h.e.f.h.\.D.
    0030:  6f 00 63 00 75 00 6d 00  65 00 6e 00 74 00 73 00  o.c.u.m.e.n.t.s.
    0040:  00 00 43 00 3a 00 5c 00  55 00 73 00 65 00 72 00  ..C.:.\.U.s.e.r.
    0050:  73 00 5c 00 63 00 68 00  65 00 66 00 68 00 5c 00  s.\.c.h.e.f.h.\.
    0060:  44 00 6f 00 63 00 75 00  6d 00 65 00 6e 00 74 00  D.o.c.u.m.e.n.t.
    0070:  73 00 00 00                                       s...
    

    Here is the code that I came up with to parse that output. I know that it is quite messy code, but as I said I couldn't get the other solutions here to work for Windows Stores apps. This one does. Please test it in your uses and mention if there are issues.

    ***** Edited to allow files or directories. *****

    $path = "$($env:USERPROFILE)\AppData\Local\Microsoft\WindowsApps\Skype.exe"
    $path2 = "$HOME/My Documents"
    
    function Get-ReparseTarget ($path)
    {
        #   Grabs output of fsutil
        $a = fsutil reparsepoint query $path
    
        #   Regex to capture fsutil output
        $regex = '[0-9a-fA-F]+\:\s\s(?([0-9a-fA-F]{2}\s){1,8}\s)(?([0-9a-fA-F]{2}\s){1,8}\s){0,1}.+'
    
        #   Splits and trims the "chunks" then adds them together to create an array of hex character
        $c = $a.foreach({if ($_ -match $regex) {($Matches['chunk1'] -split ' ').trim() | `
            where {$_ -ne ""};($Matches['chunk2'] -split ' ').trim() |where {$_ -ne ""}}})
    
        #   Convert an Array of Hex(String) to Array of Bytes
        $f = [byte[]]($c | foreach{[Convert]::ToInt32($_,16)})
    
        #   Convert the Unicode to Ascii and convert '' (00 in hex) to spaces
        $g = [System.Text.Encoding]::Unicode.GetChars($f).foreach({if([int]$_ -eq 0) {' '} else {$_}})
    
        #   Combine Char[] to String then Split into the important bits and Select the Reparse Target Path 
        #   depending on whether the Path argument is a file or directory
        switch ((get-item -Force -Path $path))
        {
            {$_ -is [System.IO.FileInfo]} {$h = ($g[0..($g.Count -4)] -join "" -split " ", 4)[3]}
            {$_ -is [System.IO.DirectoryInfo]} {$h = ($g[0..($g.Count -2)] -join "" -split " ", 3)[2]}
            Default { Write-Error "Path must be either a file or directory"}
        }
    
        #   Return the path
        return $h
    }
    
    #  Quick Test
    Get-ReparseTarget -path $path
    Get-ReparseTarget -path $path2
    
    
    # Input:
    #   $path = "$($env:USERPROFILE)\AppData\Local\Microsoft\WindowsApps\Skype.exe"
    # Run:
    #   Get-ReparseTarget $path
    # Returns:
    #   C:\Program Files\WindowsApps\Microsoft.SkypeApp_15.64.80.0_x86__kzf8qxf38zg5c\Skype\Skype.exe
    
    # Input:
    #   $path2 = "$HOME/My Documents"
    # Run:
    #   Get-ReparseTarget $path2
    # Returns:
    #   C:\Users\chefh\Documents
    

提交回复
热议问题