NSIS多实例产品卸载时注册表键未删除的问题
NSIS多实例卸载注册表键无法删除问题解决
问题核心
开发支持多实例部署的NSIS安装包时,通过!define appname 'vpmapclient$Environment'动态生成test/live实例对应的注册表键(如vpmapclient-test),安装后能正常显示在「程序和功能」中,但卸载时DeleteRegKey无法移除对应注册表键,导致条目残留;若用固定常量定义appname则卸载正常。
根因分析
!define是NSIS的编译时指令,在脚本编译阶段就会完成变量替换。如果$Environment是安装过程中才确定的运行时变量(比如通过命令行参数传入),那么主安装脚本编译时,$Environment还没有实际值,!define appname 'vpmapclient$Environment'会被解析成字符串vpmapclient$Environment,而非实际的vpmapclient-test或vpmapclient-live。
生成的卸载器中,${appname}会保留这个错误的固定字符串,卸载时尝试删除vpmapclient$Environment这个不存在的注册表键,自然无法清理「程序和功能」条目。而用常量定义时,appname是编译时确定的固定值,卸载器能正确匹配目标键,所以删除正常。
解决方案
改用运行时变量传递实例名称给卸载器,确保卸载时能获取到正确的注册表键名。
修改后的安装代码
; 替换编译时!define为运行时变量赋值 StrCpy $AppName "vpmapclient$Environment" ; 写入实例专属注册表项(使用运行时变量$AppName) WriteRegStr HKLM "SOFTWARE\Company\$AppName" "Install_Dir" "$INSTDIR" WriteRegStr HKLM "SOFTWARE\Company\$AppName" "DisplayVersion" "${_VERSION}" ; 写入「程序和功能」卸载注册表项(使用$AppName) WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "DisplayName" "Company Product $Environment" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "Publisher" "Company" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "VersionMajor" ${VERSIONMAJOR} WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "VersionMinor" ${VERSIONMINOR} WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "Version" 0x02000000 WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "DisplayVersion" "${_VERSION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "UninstallString" '"$INSTDIR\product_uninstall.exe"' WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "DisplayIcon" "$INSTDIR\Product.ico" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "EstimatedSize" "$EstimatedSize" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "NoModify" 1 WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "NoRepair" 1 ; 生成卸载器时,将实际的AppName传递为卸载器的编译时变量 WriteUninstaller /D=APPNAME="$AppName" "$InstDir\product_uninstall.exe"
修改后的卸载代码
; 接收安装时传递的APPNAME变量 !define APPNAME "${APPNAME}" DetailPrint "===Removing Registry Keys for ${APPNAME}===" ; 删除对应实例的注册表键 DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" DeleteRegKey HKLM "SOFTWARE\Company\${APPNAME}"
备选方案(从注册表读取实例名)
如果无法通过WriteUninstaller传递变量,可在安装时将实例名写入卸载注册表项,卸载时读取后再删除:
安装时新增写入:
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" "AppName" "$AppName"
卸载时读取并删除:
; 读取当前卸载项对应的实例名 ReadRegStr $AppName HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY}" "AppName" DetailPrint "===Removing Registry Keys for $AppName===" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\$AppName" DeleteRegKey HKLM "SOFTWARE\Company\$AppName"
内容的提问来源于stack exchange,提问作者tcweb
相关产品推荐
相关产品推荐

