diff --git a/packaging/windows/lightcraft.wxs b/packaging/windows/lightcraft.wxs index f1be9d04..a2025409 100644 --- a/packaging/windows/lightcraft.wxs +++ b/packaging/windows/lightcraft.wxs @@ -51,9 +51,19 @@ + + + + + + + Condition="LEGACYINSTALLFOLDER AND LEGACYINSTALLEXE AND NOT PREVIOUSINSTALLFOLDER AND NOT INSTALLFOLDER" /> diff --git a/packaging/windows/test-install-folder.ps1 b/packaging/windows/test-install-folder.ps1 index 56b41786..be7733cd 100644 --- a/packaging/windows/test-install-folder.ps1 +++ b/packaging/windows/test-install-folder.ps1 @@ -12,7 +12,8 @@ $ErrorActionPreference = 'Stop' $PSNativeCommandUseErrorActionPreference = $false $id = [Guid]::NewGuid().ToString('N') $root = Join-Path ([IO.Path]::GetTempPath()) "lightcraft-install-folder-$id" -$key = "Software\LightCraftInstallerTests\$id" +$testsKey = 'Software\LightCraftInstallerTests' +$key = "$testsKey\$id" $product = [Guid]::NewGuid().ToString('B') $upgrade = [Guid]::NewGuid().ToString('B') $view = if ($Arch -eq 'x86') { [Microsoft.Win32.RegistryView]::Registry32 } else { [Microsoft.Win32.RegistryView]::Registry64 } @@ -72,20 +73,25 @@ try { $legacy = Join-Path $root 'legacy app café' $modern = Join-Path $root 'remembered app' $explicit = Join-Path $root 'explicit app' - New-Item -ItemType Directory -Path $legacy, $modern, $explicit | Out-Null - [IO.File]::WriteAllText((Join-Path $legacy 'lightcraft.exe'), 'test placeholder; never executed') + $emptied = Join-Path $root 'emptied app' + New-Item -ItemType Directory -Path $legacy, $modern, $explicit, $emptied | Out-Null + $legacyExe = Join-Path $legacy 'lightcraft.exe' + [IO.File]::WriteAllText($legacyExe, 'test placeholder; never executed') $programFiles = if ($Arch -eq 'x86' -and ${env:ProgramFiles(x86)}) { ${env:ProgramFiles(x86)} } else { $env:ProgramFiles } $cases = @( @{ Name = 'fresh'; Expected = (Join-Path $programFiles 'LightCraft') }, - @{ Name = 'legacy-app-paths'; Legacy = $true; Expected = $legacy }, + @{ Name = 'legacy-app-paths'; Legacy = $legacyExe; Expected = $legacy }, + # A stale unquoted path with a space used to resolve to the parent of the text before the space. + @{ Name = 'legacy-folder-deleted'; Legacy = (Join-Path $root 'deleted app\lightcraft.exe'); Expected = (Join-Path $programFiles 'LightCraft') }, + @{ Name = 'legacy-exe-deleted'; Legacy = (Join-Path $emptied 'lightcraft.exe'); Expected = (Join-Path $programFiles 'LightCraft') }, @{ Name = 'remembered-folder'; Modern = $true; Expected = $modern }, - @{ Name = 'remembered-beats-legacy'; Modern = $true; Legacy = $true; Expected = $modern }, - @{ Name = 'explicit-beats-legacy'; Legacy = $true; Explicit = $true; Expected = $explicit }, - @{ Name = 'explicit-beats-both'; Modern = $true; Legacy = $true; Explicit = $true; Expected = $explicit } + @{ Name = 'remembered-beats-legacy'; Modern = $true; Legacy = $legacyExe; Expected = $modern }, + @{ Name = 'explicit-beats-legacy'; Legacy = $legacyExe; Explicit = $true; Expected = $explicit }, + @{ Name = 'explicit-beats-both'; Modern = $true; Legacy = $legacyExe; Explicit = $true; Expected = $explicit } ) foreach ($case in $cases) { $registry.DeleteSubKeyTree($key, $false) - if ($case.Legacy) { Set-TestValue 'Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe' '' (Join-Path $legacy 'lightcraft.exe') } + if ($case.Legacy) { Set-TestValue 'Software\Microsoft\Windows\CurrentVersion\App Paths\lightcraft.exe' '' $case.Legacy } if ($case.Modern) { Set-TestValue 'Software\LightCraft' 'InstallFolder' "$modern\" } $arguments = @('/i', "`"$msi`"") if ($case.Explicit) { $arguments += "INSTALLFOLDER=`"$explicit`"" } @@ -108,6 +114,12 @@ try { if ($installed) { Invoke-Msi @('/x', $product) (Join-Path $root 'cleanup.log') -AllowAbsent } } finally { $registry.DeleteSubKeyTree($key, $false) + $tests = $registry.OpenSubKey($testsKey) + if ($tests) { + $empty = $tests.SubKeyCount -eq 0 -and $tests.ValueCount -eq 0 + $tests.Dispose() + if ($empty) { $registry.DeleteSubKey($testsKey, $false) } + } $registry.Dispose() # Keep logs on failure; they explain MSI failures that otherwise only report an exit code. if ($passed) { Remove-Item -Recurse -Force $root } else { Write-Output "Test artifacts retained: $root" }