Files
zyt/app/scripts/smoke_windows_installer.ps1
2026-08-22 10:46:13 +08:00

158 lines
5.6 KiB
PowerShell

[CmdletBinding()]
param(
[string]$Installer
)
$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.Drawing
$ProjectRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
function Get-AssociatedIconHash {
param([Parameter(Mandatory = $true)][string]$FilePath)
$Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($FilePath)
if (-not $Icon) {
throw "Unable to extract the Windows icon from: $FilePath"
}
$Bitmap = New-Object System.Drawing.Bitmap 32, 32
$Graphics = [System.Drawing.Graphics]::FromImage($Bitmap)
$Stream = New-Object System.IO.MemoryStream
$Hasher = [System.Security.Cryptography.SHA256]::Create()
try {
$Graphics.Clear([System.Drawing.Color]::Transparent)
$Graphics.DrawIcon($Icon, 0, 0)
$Bitmap.Save($Stream, [System.Drawing.Imaging.ImageFormat]::Png)
$Hash = $Hasher.ComputeHash($Stream.ToArray())
return ([System.BitConverter]::ToString($Hash)).Replace("-", "")
}
finally {
$Hasher.Dispose()
$Stream.Dispose()
$Graphics.Dispose()
$Bitmap.Dispose()
$Icon.Dispose()
}
}
if (-not $Installer) {
$Installer = Get-ChildItem `
-LiteralPath (Join-Path $ProjectRoot "dist") `
-Filter "DoctorWorkstation-Setup-Windows-x64-*.exe" `
-File |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1 -ExpandProperty FullName
}
if (-not $Installer -or -not (Test-Path -LiteralPath $Installer -PathType Leaf)) {
throw "Windows installer was not found: $Installer"
}
$Installer = (Resolve-Path -LiteralPath $Installer).Path
$InstallerIconHash = Get-AssociatedIconHash -FilePath $Installer
$TempBase = [System.IO.Path]::GetFullPath([System.IO.Path]::GetTempPath())
$SmokeRoot = [System.IO.Path]::GetFullPath((Join-Path $TempBase (
"doctor-workstation-installer-smoke-" + [guid]::NewGuid().ToString("N")
)))
if (-not $SmokeRoot.StartsWith($TempBase, [System.StringComparison]::OrdinalIgnoreCase) -or
-not ([System.IO.Path]::GetFileName($SmokeRoot)).StartsWith(
"doctor-workstation-installer-smoke-"
)) {
throw "Refusing to use an unsafe installer smoke directory: $SmokeRoot"
}
$InstallDirectory = Join-Path $SmokeRoot "install"
$SetupLog = Join-Path $SmokeRoot "setup.log"
$UninstallLog = Join-Path $SmokeRoot "uninstall.log"
New-Item -ItemType Directory -Path $SmokeRoot -Force | Out-Null
$SetupProcess = Start-Process `
-FilePath $Installer `
-ArgumentList @(
"/VERYSILENT",
"/SUPPRESSMSGBOXES",
"/NORESTART",
"/CURRENTUSER",
"/DIR=$InstallDirectory",
"/MERGETASKS=!desktopicon",
"/LOG=$SetupLog"
) `
-Wait `
-PassThru `
-WindowStyle Hidden
if ($SetupProcess.ExitCode -ne 0) {
throw "Installer exited with code $($SetupProcess.ExitCode). See $SetupLog"
}
$InstalledExecutable = Join-Path $InstallDirectory "DoctorWorkstation.exe"
if (-not (Test-Path -LiteralPath $InstalledExecutable -PathType Leaf)) {
throw "Installed executable is missing: $InstalledExecutable"
}
$Uninstaller = Join-Path $InstallDirectory "unins000.exe"
if (-not (Test-Path -LiteralPath $Uninstaller -PathType Leaf)) {
throw "Uninstaller is missing: $Uninstaller"
}
$InstalledIconHash = Get-AssociatedIconHash -FilePath $InstalledExecutable
$UninstallerIconHash = Get-AssociatedIconHash -FilePath $Uninstaller
if ($InstalledIconHash -ne $InstallerIconHash) {
throw "Installed executable icon does not match the installer brand icon"
}
if ($UninstallerIconHash -ne $InstallerIconHash) {
throw "Uninstaller icon does not match the installer brand icon"
}
$Environment = @{
"DOCTOR_CONFIG_DIR" = (Join-Path $SmokeRoot "config")
"DOCTOR_LOG_DIR" = (Join-Path $SmokeRoot "logs")
"DOCTOR_API_BASE_URL" = "https://127.0.0.1:9"
"DOCTOR_DEMO_MODE" = "true"
"DOCTOR_VIDEO_MODE" = "embedded"
"DOCTOR_SMOKE_TEST" = "1"
"QT_QPA_PLATFORM" = "offscreen"
}
$PreviousEnvironment = @{}
$ApplicationExitCode = $null
$UninstallExitCode = $null
try {
foreach ($Name in $Environment.Keys) {
$PreviousEnvironment[$Name] = [Environment]::GetEnvironmentVariable($Name, "Process")
[Environment]::SetEnvironmentVariable($Name, $Environment[$Name], "Process")
}
$ApplicationProcess = Start-Process `
-FilePath $InstalledExecutable `
-ArgumentList "--smoke-test" `
-Wait `
-PassThru `
-WindowStyle Hidden
$ApplicationExitCode = $ApplicationProcess.ExitCode
}
finally {
foreach ($Name in $Environment.Keys) {
[Environment]::SetEnvironmentVariable($Name, $PreviousEnvironment[$Name], "Process")
}
if (Test-Path -LiteralPath $Uninstaller -PathType Leaf) {
$UninstallProcess = Start-Process `
-FilePath $Uninstaller `
-ArgumentList @(
"/VERYSILENT",
"/SUPPRESSMSGBOXES",
"/NORESTART",
"/LOG=$UninstallLog"
) `
-Wait `
-PassThru `
-WindowStyle Hidden
$UninstallExitCode = $UninstallProcess.ExitCode
}
}
if ($ApplicationExitCode -ne 0) {
throw "Installed application smoke test exited with code $ApplicationExitCode"
}
if ($UninstallExitCode -ne 0) {
throw "Uninstaller exited with code $UninstallExitCode. See $UninstallLog"
}
Start-Sleep -Milliseconds 500
if (Test-Path -LiteralPath $InstalledExecutable) {
throw "Uninstaller left the installed executable behind: $InstalledExecutable"
}
Write-Host "Installer icon/install/start/uninstall smoke test passed." -ForegroundColor Green
Write-Host "Smoke logs and isolated user data: $SmokeRoot"