mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-26 02:58:32 -06:00
Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
90 lines
6.0 KiB
PowerShell
90 lines
6.0 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Check the compiled MSI's shortcuts, desktop-shortcut checkbox and full-UI outcome wiring (#143), without installing it.
|
|
.EXAMPLE
|
|
pwsh packaging/windows/test-msi.ps1 dist/release/pdfcraft-0.2.1-windows-x64.msi
|
|
#>
|
|
param([Parameter(Mandatory)] [string] $Path)
|
|
$ErrorActionPreference = 'Stop'
|
|
$Installer = New-Object -ComObject WindowsInstaller.Installer
|
|
$Database = $Installer.OpenDatabase((Resolve-Path -LiteralPath $Path).Path, 0)
|
|
|
|
function Read-Row([string] $Sql, [int] $Columns) {
|
|
$view = $Database.OpenView($Sql)
|
|
try {
|
|
[void] $view.Execute()
|
|
$record = $view.Fetch()
|
|
if (-not $record) { throw "MSI row missing: $Sql" }
|
|
$values = @(for ($i = 1; $i -le $Columns; $i++) { $record.StringData($i) })
|
|
return ,$values
|
|
} finally { [void] $view.Close() }
|
|
}
|
|
|
|
function Assert-Equal($Actual, $Expected, [string] $What) {
|
|
if ($Actual -cne $Expected) { throw "$What`: expected '$Expected', got '$Actual'" }
|
|
}
|
|
|
|
# Plain (non-advertised) shortcuts to pdfcraft.exe, each in its own component; the desktop one is
|
|
# gated by INSTALLDESKTOPSHORTCUT, which defaults to 1 and is secure so the UI choice reaches the
|
|
# elevated install.
|
|
foreach ($entry in @(@('StartMenuShortcut', 'ProgramMenuFolder', 'PdfcraftStartMenuShortcut', ''),
|
|
@('DesktopShortcut', 'DesktopFolder', 'PdfcraftDesktopShortcut', 'INSTALLDESKTOPSHORTCUT = 1'))) {
|
|
$row = Read-Row ('SELECT `Directory_`, `Target`, `Icon_`, `WkDir`, `Component_` FROM `Shortcut` WHERE `Shortcut` = ''' + $entry[0] + '''') 5
|
|
Assert-Equal $row[0] $entry[1] "$($entry[0]) directory"
|
|
Assert-Equal $row[1] '[#PdfcraftExe]' "$($entry[0]) target"
|
|
Assert-Equal $row[2] 'PdfcraftIcon.ico' "$($entry[0]) icon"
|
|
Assert-Equal $row[3] 'INSTALLFOLDER' "$($entry[0]) working directory"
|
|
Assert-Equal $row[4] $entry[2] "$($entry[0]) component"
|
|
$component = Read-Row ('SELECT `Directory_`, `Condition` FROM `Component` WHERE `Component` = ''' + $entry[2] + '''') 2
|
|
Assert-Equal $component[0] $entry[1] "$($entry[2]) directory"
|
|
Assert-Equal $component[1] $entry[3] "$($entry[2]) condition"
|
|
}
|
|
$default = Read-Row 'SELECT `Value` FROM `Property` WHERE `Property` = ''INSTALLDESKTOPSHORTCUT''' 1
|
|
Assert-Equal $default[0] '1' 'Desktop shortcut default'
|
|
$secure = Read-Row 'SELECT `Value` FROM `Property` WHERE `Property` = ''SecureCustomProperties''' 1
|
|
if (($secure[0] -split ';') -notcontains 'INSTALLDESKTOPSHORTCUT') { throw "INSTALLDESKTOPSHORTCUT is not secure: '$($secure[0])'" }
|
|
$checkbox = Read-Row 'SELECT `Type`, `Property`, `Text` FROM `Control` WHERE `Dialog_` = ''InstallWelcome'' AND `Control` = ''DesktopShortcut''' 3
|
|
Assert-Equal $checkbox[0] 'CheckBox' 'Welcome desktop-shortcut control'
|
|
Assert-Equal $checkbox[1] 'INSTALLDESKTOPSHORTCUT' 'Welcome checkbox property'
|
|
if ($checkbox[2] -notmatch 'desktop shortcut') { throw "Welcome checkbox label: '$($checkbox[2])'" }
|
|
$checked = Read-Row 'SELECT `Value` FROM `CheckBox` WHERE `Property` = ''INSTALLDESKTOPSHORTCUT''' 1
|
|
Assert-Equal $checked[0] '1' 'Welcome checkbox value'
|
|
$app = Read-Row 'SELECT `KeyPath` FROM `Component` WHERE `Component` = ''PdfcraftApp''' 1
|
|
Assert-Equal $app[0] 'PdfcraftExe' 'Shortcut executable key path'
|
|
$scope = Read-Row 'SELECT `Value` FROM `Property` WHERE `Property` = ''ALLUSERS''' 1
|
|
Assert-Equal $scope[0] '1' 'Per-machine shortcut scope'
|
|
|
|
# Image context menu opens the DPI chooser; the app component owns every registry row so
|
|
# uninstall removes it. No image default association is changed.
|
|
foreach ($ext in @('png', 'jpg', 'jpeg', 'tif', 'tiff', 'gif', 'bmp', 'jp2', 'j2k', 'jpx')) {
|
|
$key = 'Software\Classes\SystemFileAssociations\.' + $ext + '\shell\PdfCraft.CreatePdf'
|
|
$menu = Read-Row ('SELECT `Value`, `Component_`, `Root` FROM `Registry` WHERE `Key` = ''' + $key + ''' AND `Name` IS NULL') 3
|
|
Assert-Equal $menu[0] 'Create PDF with PdfCraft…' "$ext context menu label"
|
|
Assert-Equal $menu[1] 'PdfcraftApp' "$ext context menu component"
|
|
Assert-Equal $menu[2] '2' "$ext context menu HKLM root"
|
|
$command = Read-Row ('SELECT `Value` FROM `Registry` WHERE `Key` = ''' + $key + '\command''') 1
|
|
Assert-Equal $command[0] '"[#PdfcraftExe]" --create-images "%1"' "$ext context menu command"
|
|
$selection = Read-Row ('SELECT `Value` FROM `Registry` WHERE `Key` = ''' + $key + ''' AND `Name` = ''MultiSelectModel''') 1
|
|
Assert-Equal $selection[0] 'Single' "$ext context menu selection"
|
|
}
|
|
|
|
# Negative sequences are Windows Installer's success/user-exit/failure paths. Only full UI
|
|
# shows these dialogs: an unattended /qn or /qb install must never wait for a Finish click.
|
|
foreach ($exit in @(@('InstallComplete', '-1'), @('InstallCancelled', '-2'), @('InstallFailed', '-3'))) {
|
|
$row = Read-Row ('SELECT `Condition`, `Sequence` FROM `InstallUISequence` WHERE `Action` = ''' + $exit[0] + '''') 2
|
|
Assert-Equal $row[0] 'UILevel = 5' "$($exit[0]) UI level"
|
|
Assert-Equal $row[1] $exit[1] "$($exit[0]) exit path"
|
|
$finish = Read-Row ('SELECT `Type`, `Text` FROM `Control` WHERE `Dialog_` = ''' + $exit[0] + ''' AND `Control` = ''Finish''') 2
|
|
Assert-Equal $finish[0] 'PushButton' "$($exit[0]) Finish control"
|
|
Assert-Equal $finish[1] '&Finish' "$($exit[0]) Finish label"
|
|
$endDialog = Read-Row ('SELECT `Argument` FROM `ControlEvent` WHERE `Dialog_` = ''' + $exit[0] + ''' AND `Control_` = ''Finish'' AND `Event` = ''EndDialog''') 1
|
|
Assert-Equal $endDialog[0] 'Return' "$($exit[0]) Finish event"
|
|
}
|
|
$title = Read-Row 'SELECT `Text` FROM `Control` WHERE `Dialog_` = ''InstallComplete'' AND `Control` = ''Title''' 1
|
|
if ($title[0] -notmatch 'completed successfully') { throw 'Success dialog does not confirm completion' }
|
|
$rm = Read-Row 'SELECT `Dialog` FROM `Dialog` WHERE `Dialog` = ''MsiRMFilesInUse''' 1
|
|
Assert-Equal $rm[0] 'MsiRMFilesInUse' 'Files-in-use dialog'
|
|
[void] [Runtime.InteropServices.Marshal]::FinalReleaseComObject($Database)
|
|
[void] [Runtime.InteropServices.Marshal]::FinalReleaseComObject($Installer)
|
|
Write-Output 'ok MSI: Start Menu shortcut, optional desktop shortcut (default on, checkbox), icon/key path, full-UI success/cancel/error and Finish controls, files-in-use dialog'
|