如何创建相对符号链接powershell方式?

Ant*_*lov 5 powershell file-io

在PowerShell 5.1中创建相对符号链接并不是那么简单.New-Item没有按预期工作.下面列出了一些方法.我错过了什么吗?

所有示例的示例设置:

mkdir C:\Temp\foo -ErrorAction SilentlyContinue
'sample contents' > C:\Temp\foo\foo.txt
cd C:\Temp
Run Code Online (Sandbox Code Playgroud)

Sample1:不能按预期工作

#new ps5 Item cmdlets (https://msdn.microsoft.com/en-us/powershell/wmf/5.0/feedback_symbolic) are not working well with relative paths
#C:\Temp\foo and C:\Temp\foo\foo.txt are returned
$fld = New-Item -ItemType SymbolicLink -Name 'bar' -Target '.\foo'
$fl = New-Item -ItemType SymbolicLink -Name 'bar.txt' -Target '.\foo\foo.txt'
$fld.Target
$fl.Target
Run Code Online (Sandbox Code Playgroud)

Sample2:不能按预期工作

#Powershell community extensions
#same problem - paths are created as absolute: C:\Temp\foo C:\Temp\foo\foo.txt
$fld = New-Symlink 'c:\Temp\bar' '.\foo'
$fl = New-Symlink 'c:\Temp\bar.txt' '.\foo\foo.txt'
$fld.Target
$fl.Target
Run Code Online (Sandbox Code Playgroud)

Sample3:按预期工作

#API call CreateSymbolicLink as per https://gallery.technet.microsoft.com/scriptcenter/new-symlink-60d2531e
#.\foo and .\foo\foo.txt are returned
Add-Type -MemberDefinition @'
    [DllImport("kernel32.dll", EntryPoint = "CreateSymbolicLinkW", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);

    public static DirectoryInfo CreateSymbolicLinkToFolder(string lpSymlinkFileName, string lpTargetFileName) {
        bool res = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, 1);
        if (!res) { throw new Win32Exception(Marshal.GetLastWin32Error()); }
        return (new DirectoryInfo(lpSymlinkFileName));
    }

    public static FileInfo CreateSymbolicLinkToFile(string lpSymlinkFileName, string lpTargetFileName) {
        bool res = CreateSymbolicLink(lpSymlinkFileName, lpTargetFileName, 0);
        if (!res) { throw new Win32Exception(Marshal.GetLastWin32Error()); }
        return (new FileInfo(lpSymlinkFileName));
    }
'@ -Name Win32 -NameSpace System -UsingNamespace System.ComponentModel, System.IO
[Win32]::CreateSymbolicLinkToFolder("c:\Temp\bar", ".\foo")
[Win32]::CreateSymbolicLinkToFile("c:\Temp\bar.txt", ".\foo\foo.txt")
Run Code Online (Sandbox Code Playgroud)

Sample4:按预期工作

#using mklink from cmd produces correct relative paths
#.\foo and .\foo\foo.txt are returned
cmd /c mklink /d "c:\Temp\bar" ".\foo"
cmd /c mklink "c:\Temp\bar.txt" ".\foo\foo.txt"
(Get-Item "c:\Temp\bar").Target
(Get-Item "c:\Temp\bar.txt").Target
Run Code Online (Sandbox Code Playgroud)

编辑:Sample3已更新为unicode api entry和GetLastError

Ant*_*lov 1

从 pwsh 7.1.X Sample1 开始按预期工作:

#new ps5 Item cmdlets (https://msdn.microsoft.com/en-us/powershell/wmf/5.0/feedback_symbolic) are not working well with relative paths
#C:\Temp\foo and C:\Temp\foo\foo.txt are returned
$fld = New-Item -ItemType SymbolicLink -Name 'bar' -Target '.\foo'
$fl = New-Item -ItemType SymbolicLink -Name 'bar.txt' -Target '.\foo\foo.txt'
$fld.Target
$fl.Target
Run Code Online (Sandbox Code Playgroud)