Private/WinGet/Get-WinGetWrapperScriptContent.ps1

function Get-WinGetLogDirectoryScriptFragment {
    [CmdletBinding()]
    [OutputType([string])]
    param()

    return @"
function Test-HydrationWinGetLogDirectory {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]`$Path
    )
 
    if ([string]::IsNullOrWhiteSpace(`$Path)) {
        return `$false
    }
 
    try {
        if (-not (Test-Path -Path `$Path)) {
            `$null = New-Item -Path `$Path -ItemType Directory -Force -ErrorAction Stop
        }
 
        `$probePath = Join-Path -Path `$Path -ChildPath ("IntuneHydrationKit-LogProbe-`$([guid]::NewGuid().ToString('N')).tmp")
        Set-Content -Path `$probePath -Value '' -Encoding utf8 -ErrorAction Stop
        Remove-Item -Path `$probePath -Force -ErrorAction SilentlyContinue
        return `$true
    } catch {
        return `$false
    }
}
 
function Get-HydrationWinGetLogDirectory {
    [CmdletBinding()]
    param()
 
    `$programDataPath = if (-not [string]::IsNullOrWhiteSpace(`$env:ProgramData)) {
        `$env:ProgramData
    } else {
        'C:\ProgramData'
    }
 
    `$candidatePaths = [System.Collections.Generic.List[string]]::new()
    `$candidatePaths.Add((Join-Path -Path `$programDataPath -ChildPath 'Microsoft\IntuneManagementExtension\Logs'))
 
    if (-not [string]::IsNullOrWhiteSpace(`$env:LOCALAPPDATA)) {
        `$candidatePaths.Add((Join-Path -Path `$env:LOCALAPPDATA -ChildPath 'IntuneHydrationKit\Logs'))
    }
 
    if (-not [string]::IsNullOrWhiteSpace(`$env:TEMP)) {
        `$candidatePaths.Add((Join-Path -Path `$env:TEMP -ChildPath 'IntuneHydrationKit\Logs'))
    }
 
    `$systemTempPath = [System.IO.Path]::GetTempPath()
    if (-not [string]::IsNullOrWhiteSpace(`$systemTempPath)) {
        `$candidatePaths.Add((Join-Path -Path `$systemTempPath -ChildPath 'IntuneHydrationKit\Logs'))
    }
 
    `$seenPaths = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
    foreach (`$candidatePath in `$candidatePaths) {
        if ([string]::IsNullOrWhiteSpace(`$candidatePath) -or -not `$seenPaths.Add(`$candidatePath)) {
            continue
        }
 
        if (Test-HydrationWinGetLogDirectory -Path `$candidatePath) {
            return `$candidatePath
        }
    }
 
    throw 'No writable log directory was available for WinGet script execution.'
}
"@

}

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 'Resolving WinGet for current execution context.'
    $logDirectoryFragment = Get-WinGetLogDirectoryScriptFragment

    return @"
`$ErrorActionPreference = 'Stop'
`$packageIdentifier = '$escapedPackageIdentifier'
`$operationName = '$escapedOperation'
 
$logDirectoryFragment
 
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-HydrationWinGetLogDirectory
`$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
}
"@

}