Public/New-ItemLink.ps1

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) {
                        # The UNC target of an existing item's .Target is returned in the format 'UNC\*', thus requiring formatting as '\\*' for evaluation
                        $matchInfo = $item.Target | Select-String -Pattern '^UNC\\(.*)'
                        $itemTarget = if ($matchInfo) { "\\$($matchInfo.Matches.Groups[1].Value)" } else { $item.Target }
                        if ($itemTarget -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) {
                        $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
        }
    }
}