You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

117 lines
6.8 KiB

param(
[string]$MsiPath = (Join-Path $PSScriptRoot '..\..\installer\output\Housing.msi'),
[string]$FixtureRoot = (Join-Path $PSScriptRoot '..\..\obj\installer-checks')
)
$ErrorActionPreference = 'Stop'
$MsiPath = (Resolve-Path -LiteralPath $MsiPath).Path
$fixture = Join-Path ([IO.Path]::GetFullPath($FixtureRoot)) ([Guid]::NewGuid().ToString('N'))
$desktop = Join-Path $fixture 'OneDrive\Desktop'
$localData = Join-Path $fixture 'LocalAppData'
New-Item -ItemType Directory -Force -Path $desktop, $localData | Out-Null
$script:checks = 0
function Assert-Check($Condition, [string]$Message) {
if (-not $Condition) { throw "FAIL: $Message" }
$script:checks++
}
# Open the database read-only. No InstallInitialize/InstallExecute/InstallFinalize actions run.
$installer = New-Object -ComObject WindowsInstaller.Installer
$database = $installer.OpenDatabase($MsiPath, 0)
function Read-Rows([string]$Query, [int]$Columns) {
$view = $database.OpenView($Query)
[void]$view.Execute()
while ($record = $view.Fetch()) {
$values = @(for ($column = 1; $column -le $Columns; $column++) { $record.StringData($column) })
,$values
}
[void]$view.Close()
}
$folder = @(Read-Rows "SELECT Directory_Parent, DefaultDir FROM Directory WHERE Directory = 'DESKTOPSETTINGSFOLDER'" 2)
Assert-Check ($folder.Count -eq 1 -and $folder[0][0] -eq 'DesktopFolder' -and $folder[0][1] -eq 'Housing') 'desktop Housing folder'
$shortcut = @(Read-Rows "SELECT Directory_, Target, WkDir, Icon_ FROM Shortcut WHERE Shortcut = 'HousingDesktopShortcut'" 4)
Assert-Check ($shortcut.Count -eq 1 -and $shortcut[0][0] -eq 'DesktopFolder' -and
$shortcut[0][1] -eq '[INSTALLFOLDER]Housing.exe' -and $shortcut[0][2] -eq 'INSTALLFOLDER' -and
$shortcut[0][3] -eq 'HousingIcon.exe') 'desktop shortcut target, working directory and icon'
$names = @('Hardware', 'Database', 'InspectionSettings')
$defaultConditions = @{}
$migrationConditions = @{}
foreach ($name in $names) {
$component = @(Read-Rows "SELECT Directory_, Attributes, Condition FROM Component WHERE Component = 'Desktop${name}Settings'" 3)
Assert-Check ($component.Count -eq 1 -and $component[0][0] -eq 'DESKTOPSETTINGSFOLDER') "$name destination"
$attributes = [int]$component[0][1]
Assert-Check (($attributes -band 16) -and ($attributes -band 128)) "$name Permanent and NeverOverwrite"
$defaultConditions[$name] = $component[0][2]
$migration = @(Read-Rows "SELECT Condition FROM Component WHERE Component = 'Migrate${name}Settings'" 1)
$migrationConditions[$name] = $migration[0][0]
$copy = @(Read-Rows "SELECT SourceFolder, DestFolder, Options FROM MoveFile WHERE FileKey = 'CopyLegacy$name'" 3)
Assert-Check ($copy.Count -eq 1 -and $copy[0][0] -eq ('LEGACY_' + $name.ToUpperInvariant()) -and
$copy[0][1] -eq 'DESKTOPSETTINGSFOLDER' -and $copy[0][2] -eq '0') "$name migration copies without deleting source"
}
Add-Type @'
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class SettingsMsiCheck {
[DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern uint MsiOpenPackageEx(string path, uint options, out uint handle);
[DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern uint MsiSetProperty(uint handle, string name, string value);
[DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern uint MsiGetProperty(uint handle, string name, StringBuilder value, ref uint size);
[DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern uint MsiDoAction(uint handle, string action);
[DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern int MsiEvaluateCondition(uint handle, string condition);
[DllImport("msi.dll")] public static extern uint MsiCloseHandle(uint handle);
[DllImport("msi.dll")] public static extern uint MsiSetInternalUI(uint level, IntPtr owner);
}
'@
function Get-MsiProperty([uint32]$Handle, [string]$Name) {
$value = New-Object Text.StringBuilder 4096
[uint32]$size = $value.Capacity
$result = [SettingsMsiCheck]::MsiGetProperty($Handle, $Name, $value, [ref]$size)
if ($result -ne 0) { throw "MsiGetProperty failed: $result" }
$value.ToString()
}
$previousUi = [SettingsMsiCheck]::MsiSetInternalUI(2, [IntPtr]::Zero)
try {
foreach ($scenario in @('fresh', 'legacy', 'existing-desktop')) {
if ($scenario -eq 'legacy') {
New-Item -ItemType Directory -Force -Path (Join-Path $localData 'Housing'), (Join-Path $localData 'AMO Housing') | Out-Null
foreach ($name in $names) { Set-Content -LiteralPath (Join-Path $localData "Housing\$name.ini") -Value 'old settings' }
Set-Content -LiteralPath (Join-Path $localData 'AMO Housing\InspectionSettings.ini') -Value 'saved limits'
}
if ($scenario -eq 'existing-desktop') {
New-Item -ItemType Directory -Force -Path (Join-Path $desktop 'Housing') | Out-Null
foreach ($name in $names) { Set-Content -LiteralPath (Join-Path $desktop "Housing\$name.ini") -Value 'desktop settings' }
}
[uint32]$handle = 0
$result = [SettingsMsiCheck]::MsiOpenPackageEx($MsiPath, 1, [ref]$handle)
if ($result -ne 0) { throw "MsiOpenPackageEx failed: $result" }
try {
foreach ($entry in @{ DesktopFolder = $desktop + '\'; LocalAppDataFolder = $localData + '\' }.GetEnumerator()) {
$result = [SettingsMsiCheck]::MsiSetProperty($handle, $entry.Key, $entry.Value)
if ($result -ne 0) { throw "MsiSetProperty failed: $result" }
}
$result = [SettingsMsiCheck]::MsiDoAction($handle, 'AppSearch')
if ($result -ne 0) { throw "AppSearch failed: $result" }
if (Get-MsiProperty $handle 'LEGACY_SAVED_INSPECTION') {
$result = [SettingsMsiCheck]::MsiDoAction($handle, 'SetLEGACY_INSPECTIONSETTINGS')
if ($result -ne 0) { throw "Inspection migration selection failed: $result" }
Assert-Check ((Get-MsiProperty $handle 'LEGACY_INSPECTIONSETTINGS') -eq
(Join-Path $localData 'AMO Housing\InspectionSettings.ini')) "$scenario saved limits precedence"
}
foreach ($name in $names) {
Assert-Check ([SettingsMsiCheck]::MsiEvaluateCondition($handle, $defaultConditions[$name]) -eq
[int]($scenario -eq 'fresh')) "$scenario $name default selection"
Assert-Check ([SettingsMsiCheck]::MsiEvaluateCondition($handle, $migrationConditions[$name]) -eq
[int]($scenario -eq 'legacy')) "$scenario $name migration selection"
}
}
finally { [void][SettingsMsiCheck]::MsiCloseHandle($handle) }
}
}
finally { [void][SettingsMsiCheck]::MsiSetInternalUI($previousUi, [IntPtr]::Zero) }
Write-Host "PASS: $script:checks installer checks; no product was installed."