modules/WinGet-Initialize.psm1
Set-StrictMode -Version 3 Import-Module "$PSScriptRoot\WinGet-Utils.psm1" [string]$PackageDatabase = "$PSScriptRoot\winget.packages.json" [string]$IgnoreFilePath = "$PSScriptRoot\winget.{HOSTNAME}.ignore" <# .DESCRIPTION This is the back end handler for initializing various user-facing files that typically are expected to resize external to the module install location but symlinked. .NOTES Admin rights may or may not be necessary if the user's security policy has been updated to permit creating symlinks. See "Local Security Policy": "Local Policies\User Rights Assignment\Create symbolic links". #> function Initialize-WinGetResource { param( # The path to an existing file. This file will be symbolically linked. [string]$SourceFile, # Points to one of the internally referenced resource files which # the -SourceFile will be SymLink'd or copied to. [string]$DestinationFile ) $DestinationFilename = $(Split-Path -Leaf $DestinationFile) if (-not([string]::IsNullOrWhiteSpace($SourceFile))) { if ((Test-Path $DestinationFile) -and -not(Test-ReparsePoint $DestinationFile)) { Write-Output "Backing up existing '$DestinationFilename'." Move-Item $DestinationFile -Destination "$DestinationFile.bak" -Force } $symLinkArgs = @{ ItemType = "SymbolicLink" Path = "$(Split-Path -Parent $DestinationFile)" Name = $DestinationFilename Value = "$($SourceFile | Resolve-Path)" Force = $true } Write-Output "Creating new symlink for '$DestinationFilename'." try { $null = New-Item @symLinkArgs } catch { Write-Output "An error occurred while creating a symbolic link ($($_.FullyQualifiedErrorId))." } } elseif (Test-Path $DestinationFile) { Write-Output "The '$DestinationFilename' file is already initialized." return } else { $currentVersion = [version]"0.0" if (-not[version]::TryParse((Split-Path -Leaf (Get-Item $PSScriptRoot/..)), [ref]$currentVersion)) { # Not installed as a module, do not try to migrate Write-Output "Not installed as a module. Migration of '$DestinationFilename' cannot be performed." return } $selectedVersion = [version]"0.0" $selectedPackageFile = $null $moduleVersionPaths = Get-ChildItem -Directory $PSScriptRoot/../.. $moduleVersionPaths | Where-Object { [version]($_.Name) -ne $currentVersion } | ForEach-Object { $packageFile = (Join-Path $_ "modules/$DestinationFilename") if (Test-Path $packageFile) { $version = [version](Split-Path -Leaf $_) if ($version -gt $selectedVersion) { $selectedVersion = $version $selectedPackageFile = $packageFile } } } if ($null -ne $selectedPackageFile) { $source = Get-Item $selectedPackageFile if ($source.Target) { Write-Output "Creating new symlink to '$DestinationFilename'." $symLinkArgs = @{ ItemType = "SymbolicLink" Path = "$(Split-Path -Parent $DestinationFile)" Name = $DestinationFilename Value = $source.Target } try { $null = New-Item @symLinkArgs } catch { Write-Output "An error occurred while creating a symbolic link ($($_.FullyQualifiedErrorId))." } } else { Write-Output "Copying existing '$DestinationFilename'." Copy-Item -Path $source.FullName -Destination $DestinationFile } } else { Write-Output "No '$DestinationFilename' detected." Write-Output "Create one and provide it as the argument to -SourceFile." } } } <# .DESCRIPTION Initialize the local "winget.software.json" needed by Restore-WinGetSoftware. If -SourceFile is specified, the file will be symbolically linked to the appropriate location. When this parameter is not specified, the cmdlet will auto-detect other installed module versions and attempt to find the latest existing "winget.packages.json". In such cases, it will make a symlink only if one was used previously; otherwise it will copy the previous file. .EXAMPLE PS> Initialize-WinGetRestore -SourceFile "./winget.software.json" .EXAMPLE PS> Initialize-WinGetRestore #> function Initialize-WinGetRestore { param( <# The path to an existing "winget.software.json" file. This file will be symbolically linked. #> [string]$SourceFile, <# When set, the cmdlet will automatically relaunch using an Administrator PowerShell instance. This cmdlet needs such permissions to create Symbolic Links. #> [switch]$Administrator ) if ($Administrator -and -not(Test-Administrator)) { $boundParamsString = $PSBoundParameters.Keys | ForEach-Object { if ($PSBoundParameters[$_] -is [switch]) { if ($PSBoundParameters[$_]) { "-$($_)" } } else { "-$($_) $($PSBoundParameters[$_])" } } $cmdArgs = "-NoLogo -NoExit -Command Initialize-WinGetRestore $($boundParamsString -join ' ')" Start-Process -Verb RunAs -FilePath "pwsh" -ArgumentList $cmdArgs return } Initialize-WinGetResource -SourceFile $SourceFile -DestinationFile $PackageDatabase } <# .DESCRIPTION Initialize the local "winget.{HOSTNAME}.ignore" used by various cmdlets. If -SourceFile is specified, the file will be symbolically linked to the appropriate location. When this parameter is not specified, the cmdlet will auto-detect other installed module versions and attempt to find the latest existing "winget.{HOSTNAME}.ignore". In such cases, it will make a symlink only if one was used previously; otherwise it will copy the previous file. .EXAMPLE PS> Initialize-WinGetIgnore -SourceFile "./winget.example-hostname.ignore" .EXAMPLE PS> Initialize-WinGetIgnore #> function Initialize-WinGetIgnore { param( <# The path to an existing winget-ignore file. This file will be symbolically linked. #> [string]$SourceFile, <# When set, the cmdlet will automatically relaunch using an Administrator PowerShell instance. This cmdlet needs such permissions to create Symbolic Links. #> [switch]$Administrator ) if ($Administrator -and -not(Test-Administrator)) { $boundParamsString = $PSBoundParameters.Keys | ForEach-Object { if ($PSBoundParameters[$_] -is [switch]) { if ($PSBoundParameters[$_]) { "-$($_)" } } else { "-$($_) $($PSBoundParameters[$_])" } } $cmdArgs = "-NoLogo -NoExit -Command Initialize-WinGetIgnore $($boundParamsString -join ' ')" Start-Process -Verb RunAs -FilePath "pwsh" -ArgumentList $cmdArgs return } $ignoreFile = $IgnoreFilePath.Replace('{HOSTNAME}', $(hostname).ToLower()) Initialize-WinGetResource -SourceFile $SourceFile -DestinationFile $ignoreFile } |