Private/WinGet/Get-WinGetWrapperScriptContent.ps1
|
function Get-WinGetWrapperScriptContent { [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [string]$WingetCommand, [Parameter(Mandatory)] [string]$PackageIdentifier, [Parameter(Mandatory)] [ValidateSet('Install', 'Uninstall')] [string]$Operation ) $escapedCommand = $WingetCommand -replace "'", "''" $escapedPackageIdentifier = $PackageIdentifier -replace "'", "''" $escapedOperation = $Operation -replace "'", "''" $bootstrapFragment = Get-WinGetBootstrapScriptFragment -LogFunctionName 'Write-WinGetWrapperLog' -BootstrapMessage 'Bootstrapping WinGet for SYSTEM context.' return @" `$ErrorActionPreference = 'Stop' `$packageIdentifier = '$escapedPackageIdentifier' `$operationName = '$escapedOperation' function Get-IntuneManagementExtensionLogDirectory { [CmdletBinding()] param() `$programDataPath = if (-not [string]::IsNullOrWhiteSpace(`$env:ProgramData)) { `$env:ProgramData } else { 'C:\ProgramData' } `$logDirectory = Join-Path -Path `$programDataPath -ChildPath 'Microsoft\IntuneManagementExtension\Logs' if (-not (Test-Path -Path `$logDirectory)) { `$null = New-Item -Path `$logDirectory -ItemType Directory -Force } return `$logDirectory } function Get-WinGetWrapperLogFileName { [CmdletBinding()] param() `$safePackageIdentifier = (`$packageIdentifier -replace '[^A-Za-z0-9._-]+', '-').Trim('-') if ([string]::IsNullOrWhiteSpace(`$safePackageIdentifier)) { `$safePackageIdentifier = 'package' } return "IntuneHydrationKit-WinGet-`$operationName-`$safePackageIdentifier.log" } function Write-WinGetWrapperLog { [CmdletBinding()] param( [Parameter(Mandatory)] [string]`$Message, [Parameter()] [ValidateSet('INFO', 'WARN', 'ERROR')] [string]`$Level = 'INFO' ) `$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff' Add-Content -Path `$script:logPath -Value "``[`$timestamp``] ``[`$Level``] `$Message" } function Write-WinGetProcessStreamToLog { [CmdletBinding()] param( [Parameter(Mandatory)] [string]`$Path, [Parameter(Mandatory)] [string]`$Label, [Parameter()] [ValidateSet('INFO', 'WARN', 'ERROR')] [string]`$Level = 'INFO' ) if (-not (Test-Path -Path `$Path)) { return } `$lines = @(Get-Content -Path `$Path -ErrorAction SilentlyContinue) if (`$lines.Count -eq 0) { return } Write-WinGetWrapperLog -Message "`${Label}:" -Level `$Level foreach (`$line in `$lines) { if ([string]::IsNullOrWhiteSpace(`$line)) { continue } Write-WinGetWrapperLog -Message `$line -Level `$Level } } function Test-WinGetAlreadyInstalledNoUpgradeOutput { [CmdletBinding()] param( [Parameter()] [string[]]`$Output ) `$outputText = (`$Output -join [Environment]::NewLine) `$foundExistingPackage = `$outputText -match 'Found an existing package already installed\. Trying to upgrade the installed package' `$noUpgradeAvailable = `$outputText -match 'No available upgrade found' -or `$outputText -match 'No newer package versions are available' return `$foundExistingPackage -and `$noUpgradeAvailable } $bootstrapFragment `$wingetCommand = '$escapedCommand' `$argumentString = (`$wingetCommand -replace '^\s*winget(?:\.exe)?\s*', '').Trim() if ([string]::IsNullOrWhiteSpace(`$argumentString)) { throw "Unable to derive WinGet arguments from command '`$wingetCommand'." } `$logDirectory = Get-IntuneManagementExtensionLogDirectory `$logFileName = Get-WinGetWrapperLogFileName `$script:logPath = Join-Path -Path `$logDirectory -ChildPath `$logFileName `$baseLogName = [System.IO.Path]::GetFileNameWithoutExtension(`$logFileName) `$stdoutPath = Join-Path -Path `$logDirectory -ChildPath "`$baseLogName.stdout.log" `$stderrPath = Join-Path -Path `$logDirectory -ChildPath "`$baseLogName.stderr.log" foreach (`$streamPath in @(`$stdoutPath, `$stderrPath)) { if (Test-Path -Path `$streamPath) { Remove-Item -Path `$streamPath -Force -ErrorAction SilentlyContinue } } Write-WinGetWrapperLog -Message "Starting `$operationName for package '`$packageIdentifier'." Write-WinGetWrapperLog -Message "Resolved IME log path: `$script:logPath" Write-WinGetWrapperLog -Message "Executing WinGet command: `$wingetCommand" try { `$wingetPath = Get-WinGetExecutablePath Write-WinGetWrapperLog -Message "Resolved winget executable: `$wingetPath" `$process = Start-Process -FilePath `$wingetPath -ArgumentList `$argumentString -Wait -PassThru -NoNewWindow -RedirectStandardOutput `$stdoutPath -RedirectStandardError `$stderrPath Write-WinGetProcessStreamToLog -Path `$stdoutPath -Label 'WinGet standard output' Write-WinGetProcessStreamToLog -Path `$stderrPath -Label 'WinGet standard error' -Level 'WARN' `$standardOutput = if (Test-Path -Path `$stdoutPath) { @(Get-Content -Path `$stdoutPath -ErrorAction SilentlyContinue) } else { @() } `$exitCode = [int]`$process.ExitCode Write-WinGetWrapperLog -Message "WinGet process exited with code `$exitCode." if (`$operationName -eq 'Install' -and (`$exitCode -eq -1978335189 -or (Test-WinGetAlreadyInstalledNoUpgradeOutput -Output `$standardOutput))) { Write-WinGetWrapperLog -Message "Package already installed (no upgrade needed). Treating as success." -Level 'INFO' `$exitCode = 0 } exit `$exitCode } catch { Write-WinGetProcessStreamToLog -Path `$stdoutPath -Label 'WinGet standard output' Write-WinGetProcessStreamToLog -Path `$stderrPath -Label 'WinGet standard error' -Level 'WARN' Write-WinGetWrapperLog -Message "Wrapper execution failed: `$(`$_.Exception.Message)" -Level 'ERROR' throw } "@ } |