fix: normalize absent installer paths without losing directory identity

This commit is contained in:
sky
2026-09-22 23:37:30 +08:00
parent 2bc18a01ef
commit 85e08b5ba3
2 changed files with 36 additions and 5 deletions
+20 -5
View File
@@ -152,12 +152,15 @@ Function CXCanonicalDirectory
Push "安装目录必须是完整路径。 / An absolute installation path is required."
Call CXFail
${EndIf}
ClearErrors
GetFullPathName $CXPathFull "$CXPathInput"
${If} ${Errors}
; Unlike NSIS GetFullPathName, Win32's API does not require the final path
; component to exist. Never turn a failed/empty result into the drive root.
System::Call 'kernel32::GetFullPathNameW(w "$CXPathInput",i ${NSIS_MAX_STRLEN},w .r0,p 0)i.r1'
${If} $1 = 0
${OrIf} $1 >= ${NSIS_MAX_STRLEN}
Push "无法读取安装目录。 / Cannot resolve the installation directory."
Call CXFail
${EndIf}
StrCpy $CXPathFull $0
StrLen $0 $CXPathFull
StrCpy $1 $CXPathFull 1 -1
${If} $0 > 3
@@ -224,7 +227,13 @@ Function CXRememberLegacyDirectory
Push "旧版安装目录不是有效的完整路径,已停止迁移。 / The legacy installation path is not absolute."
Call CXFail
${EndIf}
GetFullPathName $CXLegacyDirectory "$0"
System::Call 'kernel32::GetFullPathNameW(w r0,i ${NSIS_MAX_STRLEN},w .r2,p 0)i.r1'
${If} $1 = 0
${OrIf} $1 >= ${NSIS_MAX_STRLEN}
Push "无法规范化旧版安装目录。 / Cannot normalize the legacy installation directory."
Call CXFail
${EndIf}
StrCpy $CXLegacyDirectory $2
StrCpy $0 $CXLegacyDirectory 1 -1
${If} $0 != "\"
StrCpy $CXLegacyDirectory "$CXLegacyDirectory\"
@@ -252,7 +261,13 @@ Function CXValidateDestination
${If} $0 == ""
Return
${EndIf}
GetFullPathName $CXDestinationFull "$INSTDIR"
System::Call 'kernel32::GetFullPathNameW(w "$INSTDIR",i ${NSIS_MAX_STRLEN},w .r0,p 0)i.r1'
${If} $1 = 0
${OrIf} $1 >= ${NSIS_MAX_STRLEN}
Push "无法规范化新版本安装目录。 / Cannot normalize the installation destination."
Call CXFail
${EndIf}
StrCpy $CXDestinationFull $0
StrCpy $0 $CXDestinationFull 1 -1
${If} $0 != "\"
StrCpy $CXDestinationFull "$CXDestinationFull\"
+16
View File
@@ -61,6 +61,19 @@ function Assert-Installed {
}
}
}
function Reset-FixtureInstallLocation {
# Tauri intentionally preserves this install-location value when keeping
# user data. The old MSI's AppSearch overrides command-line INSTALLDIR with
# it. Remove only values produced by the previous synthetic install so this
# fixture accurately represents a legacy default Program Files installation.
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\yynxxxxx\Codex-X', $true)
if ($null -ne $key) {
try {
$key.DeleteValue('', $false)
$key.DeleteValue('InstallDir', $false)
} finally { $key.Dispose() }
}
}
function Remove-TestNsis {
# _?= avoids NSIS's detached temporary uninstaller process so WaitForExit
# actually covers registry/files removal. This is NSIS's documented syntax.
@@ -84,6 +97,7 @@ try {
Invoke-Installer $Installer '/S /UPDATE'
Assert-Installed
Remove-TestNsis
Reset-FixtureInstallLocation
Write-Host 'Scenario 2: released v0.3.20 machine MSI -> current-user NSIS -> NSIS update.'
$legacyMsi = Join-Path $Work 'Codex-X-0.3.20.msi'
@@ -97,6 +111,7 @@ try {
if ($status -ne 0 -or $oldDirectory.Length -eq 0) { throw 'Could not read actual legacy MSI InstallLocation.' }
$oldPath = $oldDirectory.ToString().TrimEnd('\')
Write-Host "Actual legacy MSI InstallLocation: $oldPath"
if ($oldPath -ne (Join-Path $env:ProgramFiles 'Codex-X')) { throw 'The legacy fixture was not installed to Program Files.' }
$oldExe = Join-Path $oldPath 'codex-x.exe'
$oldHash = (Get-FileHash $oldExe).Hash
# Guard the old directory, a non-existent child, and a junction alias. None
@@ -120,6 +135,7 @@ try {
Invoke-Installer $Installer '/S /UPDATE'
Assert-Installed
Remove-TestNsis
Reset-FixtureInstallLocation
Write-Host 'Scenario 3: MSI returns 3010 after removal; separate NSIS install continues without reboot.'
# A separate fixture copy of the hash-verified released MSI requests a reboot