Files
deepseek-harness/apps/desktop/scripts/smoke-windows.ps1
T
winewill ab62f09c22 fix(desktop): report Windows extraction failures with 7-Zip evidence
The installer showed "Failed to decompress files" and discarded 7-Zip's
error output, so a failure such as security software quarantining an
extracted file could not be told apart from a full disk or a broken
download.

- InstallerExtract returns negated Win32 errors for launch failures so
  they no longer collide with 7-Zip exit codes; 7-Zip writes UTF-8 errors.
- window-frame.dll composes a report (result, archive, destination,
  Windows version, full 7-Zip output), saves it under the updater cache
  directory, and presents a task dialog with the first error line, a
  collapsible bounded excerpt, and a Copy error details button. Silent
  installs keep only the report; a missing task dialog falls back to a
  message box.
- Unsigned Windows builds name their installer *-unsigned.exe so a
  shared file cannot pass for a release artifact; version discovery
  still counts them.
- The directory smoke asserts the saved report on a broken archive and
  smoke-windows.ps1 accepts the prepared DLL.

Refs #4893
2026-09-22 12:38:05 +08:00

58 lines
2.9 KiB
PowerShell

# Run NSIS directory and replacement checks against the prepared Windows target.
param(
[Parameter(Mandatory)][string]$Makensis,
[Parameter(Mandatory)][string]$SevenZip,
[Parameter(Mandatory)][string]$PluginDir,
[string]$FrameLibrary
)
$ErrorActionPreference = 'Stop'
$desktopRoot = Split-Path $PSScriptRoot -Parent
$fixtureRoot = Join-Path $desktopRoot 'tests/fixtures'
$scratch = [System.IO.Directory]::CreateTempSubdirectory('dsh-desktop-native-').FullName
function Invoke-Checked([string]$Executable, [string[]]$Arguments) {
& $Executable @Arguments | Out-Host
if ($LASTEXITCODE -ne 0) { throw "$Executable exited with $LASTEXITCODE" }
}
try {
# The prepared window-frame.dll adds the native extraction path and its failure report to the directory checks.
$directoryArguments = @{ Makensis = $Makensis; SevenZip = $SevenZip }
if ($FrameLibrary) { $directoryArguments.FrameLibrary = $FrameLibrary }
& (Join-Path $PSScriptRoot 'smoke-installer-directories.ps1') @directoryArguments
$payload = Join-Path $scratch 'payload'
New-Item -ItemType Directory -Path $payload | Out-Null
[System.IO.File]::WriteAllText((Join-Path $payload 'locked.txt'), 'new runtime')
[System.IO.File]::WriteAllText((Join-Path $payload 'asset.txt'), 'new asset')
$archive = Join-Path $scratch 'payload.7z'
Invoke-Checked $SevenZip @('a', '-bd', '-t7z', $archive, "$payload/*")
foreach ($mode in @('copy', 'direct')) {
$target = Join-Path $scratch $mode
New-Item -ItemType Directory -Path $target | Out-Null
$locked = Join-Path $target 'locked.txt'
[System.IO.File]::WriteAllText($locked, 'old runtime')
$probeExe = Join-Path $scratch "$mode.exe"
$probeResult = Join-Path $scratch "$mode.txt"
$compileArgs = @('/V2', "/DOUTPUT_FILE=$probeExe", "/DRESULT_FILE=$probeResult", "/DPAYLOAD_FILE=$archive", "/DTARGET_DIR=$target", "/DPLUGIN_DIR=$PluginDir")
if ($mode -eq 'direct') { $compileArgs += '/DDIRECT' }
$compileArgs += Join-Path $fixtureRoot 'installer-write-failure-smoke.nsi'
Invoke-Checked $Makensis $compileArgs
$handle = [System.IO.File]::Open($locked, 'Open', 'Read', 'Read')
try { Invoke-Checked $probeExe @('/S') }
finally { $handle.Dispose() }
$flag = if ($mode -eq 'copy') { 'true' } else { 'false' }
$expected = "errorFlag=$flag`nlocked=old runtime`nasset=new asset"
if ((Get-Content -LiteralPath $probeResult -Raw).Replace("`r`n", "`n").TrimEnd() -ne $expected) {
throw "Unexpected NSIS $mode replacement result"
}
}
Write-Output 'NSIS directory/replacement smokes passed.'
} finally {
$tempRoot = [System.IO.Path]::GetFullPath([System.IO.Path]::GetTempPath())
$resolvedScratch = [System.IO.Path]::GetFullPath($scratch)
if (-not $resolvedScratch.StartsWith($tempRoot, [System.StringComparison]::OrdinalIgnoreCase)) {
throw "Refusing cleanup outside the temporary root: $resolvedScratch"
}
Remove-Item -LiteralPath $resolvedScratch -Recurse -Force
}