Public/New-ItemLink.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function New-ItemLink {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Path
        ,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Value
        ,
        [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('HardLink', 'Junction', 'SymbolicLink')]
        [string]$ItemType
        ,
        [Parameter(Mandatory=$false)]
        [switch]$Force
    )
    begin {
        $_errorActionPreference = $ErrorActionPreference
        $_path = $Path.Trim()
        $_value = $Value.Trim()
        if ($env:OS -eq 'Windows_NT') {
            $_path = $_path -replace "/","\"
            $_value = $_value -replace "/","\"
        }
    }process {
        try {
            $ErrorActionPreference = 'Stop'
            "ItemType: '$($ItemType)', Path: '$($_path)', Value: '$($_value)'" | Write-Verbose
            $item = Get-Item -Path $_path -Force -ErrorAction SilentlyContinue
            if ($item) {
                if (!$item.LinkType) {
                    throw "Existing item '$_path' is not a HardLink, Junction, or SymbolicLink."
                }
                if (!$Force) {
                    if (($item.LinkType -eq $ItemType) -and ($item.Target -eq $_value)) {
                        "Matching item '$_path' already exists. Skipping" | Write-Verbose
                        return
                    }
                }
                # New-Item with -Force cannot override an existing Junction, hence the need to remove the existing Link: Junction, SymbolicLink, or HardLink
                if ($ItemType -eq 'Junction') {
                    if ($PSVersionTable.PSVersion.Major -le 5 -and $item.Attributes -match 'ReparsePoint') {
                        $item.Delete() # Powershell 5 requires a special way to remove a SymbolicLink, see: https://stackoverflow.com/a/63172492
                    }else {
                        $item | Remove-Item -Force
                    }
                }
            }
            "Creating item '$_path'" | Write-Verbose
            New-Item -Path $_path -ItemType $ItemType -Value $_value -Force:$Force
        }catch {
            Write-Error -ErrorRecord $_ -ErrorAction $_errorActionPreference
        }
    }
}