test: verify MSI failure policy restoration on native PowerShell
This commit is contained in:
@@ -16,6 +16,10 @@ jobs:
|
||||
- name: Diagnose actual preview153 MSI as standard user
|
||||
shell: powershell
|
||||
run: ./scripts/test-msi-policy-restoration.ps1 -Case "${{ matrix.policy }}"
|
||||
- name: Verify durable cleanup guard
|
||||
if: matrix.policy == 'invalid-msi'
|
||||
shell: powershell
|
||||
run: ./scripts/test-msi-policy-cleanup.ps1
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Windows PowerShell 5.1 regression: the disposable-host policy is restored on failure.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
if ($env:GITHUB_ACTIONS -ne 'true' -or $env:RUNNER_ENVIRONMENT -ne 'github-hosted') {
|
||||
throw 'This regression requires a disposable GitHub-hosted runner'
|
||||
}
|
||||
$path = 'SOFTWARE\Policies\Microsoft\Windows\Installer'
|
||||
$originalKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path, $true)
|
||||
$hadKey = $null -ne $originalKey
|
||||
$hadValue = $hadKey -and ($originalKey.GetValueNames() -contains 'DisableMSI')
|
||||
if ($hadValue) {
|
||||
$originalValue = $originalKey.GetValue('DisableMSI', $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
||||
$originalKind = $originalKey.GetValueKind('DisableMSI')
|
||||
}
|
||||
if ($hadKey -and ($originalKey.SubKeyCount -ne 0 -or @($originalKey.GetValueNames() | Where-Object { $_ -ne 'DisableMSI' }).Count -ne 0)) {
|
||||
$originalKey.Dispose()
|
||||
throw 'Refusing to alter a host with unrelated Installer policy'
|
||||
}
|
||||
if ($null -ne $originalKey) { $originalKey.Dispose() }
|
||||
$invalid = Join-Path $env:PUBLIC ('invalid-msi-' + [guid]::NewGuid().ToString('N') + '.msi')
|
||||
'Invalid MSI fixture' | Set-Content $invalid
|
||||
try {
|
||||
foreach ($case in @('absent','dword','string')) {
|
||||
[Microsoft.Win32.Registry]::LocalMachine.DeleteSubKeyTree($path, $false)
|
||||
if ($case -ne 'absent') {
|
||||
$key = [Microsoft.Win32.Registry]::LocalMachine.CreateSubKey($path)
|
||||
if ($case -eq 'string') { $key.SetValue('DisableMSI', '1', [Microsoft.Win32.RegistryValueKind]::String) }
|
||||
else { $key.SetValue('DisableMSI', 1, [Microsoft.Win32.RegistryValueKind]::DWord) }
|
||||
$key.Dispose()
|
||||
}
|
||||
$logsBefore = @(Get-ChildItem $env:PUBLIC -Directory -Filter 'VoiceStudioMsiSmoke-*' | ForEach-Object FullName)
|
||||
$failure = $null
|
||||
try { & "$PSScriptRoot/smoke-per-user-msi.ps1" -MsiPath $invalid -PrepareHostedRunner }
|
||||
catch { $failure = $_.Exception.Message }
|
||||
if ($failure -notmatch 'standard-user install exited 1620') { throw "Unexpected invalid-MSI result: $failure" }
|
||||
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($path)
|
||||
if ($case -eq 'absent') {
|
||||
if ($null -ne $key) { $key.Dispose(); throw 'Absent policy key was not restored' }
|
||||
} else {
|
||||
if ($null -eq $key) { throw 'Original policy key missing' }
|
||||
$expectedKind = if ($case -eq 'string') { [Microsoft.Win32.RegistryValueKind]::String } else { [Microsoft.Win32.RegistryValueKind]::DWord }
|
||||
$valid = $key.GetValueKind('DisableMSI') -eq $expectedKind -and $key.GetValue('DisableMSI').ToString() -eq '1'
|
||||
$key.Dispose()
|
||||
if (-not $valid) { throw 'Policy value/type changed after failure' }
|
||||
}
|
||||
if (Get-LocalUser -Name VoiceStudioMsiTest -ErrorAction SilentlyContinue) { throw 'Test account survived failed install' }
|
||||
$newLogs = @(Get-ChildItem $env:PUBLIC -Directory -Filter 'VoiceStudioMsiSmoke-*' | Where-Object { $_.FullName -notin $logsBefore })
|
||||
if ($newLogs.Count -ne 1 -or -not (Test-Path (Join-Path $newLogs[0].FullName 'install.log'))) { throw 'Verbose failure log missing' }
|
||||
Write-Host "PASS policy restoration after invalid MSI: $case"
|
||||
}
|
||||
} finally {
|
||||
[Microsoft.Win32.Registry]::LocalMachine.DeleteSubKeyTree($path, $false)
|
||||
if ($hadKey) {
|
||||
$key = [Microsoft.Win32.Registry]::LocalMachine.CreateSubKey($path)
|
||||
if ($hadValue) { $key.SetValue('DisableMSI', $originalValue, $originalKind) }
|
||||
$key.Dispose()
|
||||
}
|
||||
Remove-Item $invalid -ErrorAction SilentlyContinue
|
||||
}
|
||||
Reference in New Issue
Block a user