如何在NSIS中检测软件安装路径并实现同路径静默更新
解决NSIS自动安装到旧版本路径的问题
你的问题核心在于当前脚本的.onInit函数硬覆盖了$INSTDIR的值,同时需要确保旧版本的安装路径被正确写入注册表,让新版本能读取到。下面是具体的修复方案:
关键问题分析
- 你虽然定义了
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "",但在.onInit中检测到64位系统时,直接用StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCT_NAME}"覆盖了从注册表读取的旧路径,这就导致新版本不管旧路径在哪,都强制装到Program Files 64位目录。 - 需要确保旧版本安装时,把实际安装路径写入注册表,这样新版本才能正确读取。
修复步骤及修改后的代码
1. 修正.onInit函数,保留注册表读取的旧路径
把原来的.onInit函数替换成以下内容,这样64位系统下会先尝试读取旧路径,而不是直接硬编码:
Function .onInit !insertmacro MULTIUSER_INIT ; 先尝试读取旧版本的安装路径(处理64位/32位注册表视图) ${If} ${RunningX64} SetRegView 64 ReadRegStr $R0 HKLM "${PRODUCT_DIR_REGKEY}" "" ${If} $R0 == "" SetRegView 32 ReadRegStr $R0 HKLM "${PRODUCT_DIR_REGKEY}" "" ${EndIf} ${Else} ReadRegStr $R0 HKLM "${PRODUCT_DIR_REGKEY}" "" ${EndIf} ; 如果读取到旧路径,就用它作为$INSTDIR ${If} $R0 != "" StrCpy $INSTDIR $R0 ${Else} ; 没有旧路径时,才用默认路径 ${If} ${RunningX64} StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCT_NAME}" ${Else} MessageBox MB_OK "${PRODUCT_NAME} needs 64bit Windows!" Abort ${EndIf} ${EndIf} ; 检查是否有旧版本需要卸载 ReadRegStr $R0 HKLM "${PRODUCT_UNINST_KEY}" "QuietUninstallString" StrCmp $R0 "" done uninst uninst: ClearErrors Exec '$R0' done: FunctionEnd
2. 确保安装时写入路径到注册表
在Section "MainSection"的末尾添加写入注册表的代码,把当前安装路径存入指定键,供后续版本读取:
Section "MainSection" SEC01 Call EnsureNotRunning ; ... 你的原有删除、复制文件代码 ... ; 写入安装路径到注册表,供后续版本读取 ${If} ${RunningX64} SetRegView 64 ${EndIf} WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\MyApp.exe" WriteRegStr HKLM "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR" SectionEnd
3. 保留默认路径的兜底逻辑
保持InstallDir作为无旧版本时的默认路径,同时确保InstallDirRegKey的优先级更高:
; 无旧版本时使用默认路径,会被注册表读取的旧路径覆盖 InstallDir "$PROGRAMFILES\${PRODUCT_NAME}" InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
额外说明
- 如果你的旧版本没有写入
${PRODUCT_DIR_REGKEY},第一个新版本还是会用默认路径,但之后的版本就能自动继承安装路径了。 - 确认
${PRODUCT_DIR_REGKEY}的路径和旧版本注册的App Paths项一致,避免读取失败。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

