InnoSetup补丁重命名安装目录后全量包无法识别卸载配置咨询
解决方案
问题本质
你遇到的问题核心是补丁包重命名安装目录后,没有同步更新Inno Setup写入注册表的卸载记录、安装路径缓存,导致后续全量包读取的还是旧的目录信息。
第一步:修改补丁包ISS配置
1. 优化重命名逻辑,同步更新注册表
把你补丁包原来的CurStepChanged方法替换为以下代码:
procedure CurStepChanged(CurStep: TSetupStep); var sUnInstPath: string; sNewAppDir: string; sUninstallExePath: string; bIsHKLM: Boolean; begin if (CurStep=ssPostInstall) then begin // 拼接新目录路径 sNewAppDir := ExpandConstant('{app}\..\{#MyAppName} {#MyAppVersion}'); // 执行目录重命名 RenameFile(ExpandConstant('{app}'), sNewAppDir); // 确定卸载注册表路径 sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); // 先判断是HKLM还是HKCU的注册表 bIsHKLM := RegValueExists(HKLM, sUnInstPath, 'UninstallString'); // 拼接新的卸载程序路径 sUninstallExePath := sNewAppDir + '\unins000.exe'; // 更新卸载注册表项 if bIsHKLM then begin RegWriteStringValue(HKLM, sUnInstPath, 'UninstallString', '"' + sUninstallExePath + '"'); RegWriteStringValue(HKLM, sUnInstPath, 'InstallLocation', sNewAppDir); RegWriteStringValue(HKLM, sUnInstPath, 'DisplayIcon', sUninstallExePath + ',0'); end else begin RegWriteStringValue(HKCU, sUnInstPath, 'UninstallString', '"' + sUninstallExePath + '"'); RegWriteStringValue(HKCU, sUnInstPath, 'InstallLocation', sNewAppDir); RegWriteStringValue(HKCU, sUnInstPath, 'DisplayIcon', sUninstallExePath + ',0'); end; end; end;
2. 保留原有[UninstallDelete]配置
你现有配置无需修改,因为卸载程序运行时{app}对应的已经是更新后的新目录路径,会正确删除对应版本目录。
第二步:优化全量包ISS配置
你原来的卸载逻辑不用大改,只需要做两处调整:
- 在
[Setup]段设置UsePreviousAppDir=false,卸载旧版本后全量包会自动创建符合规则的应用名 x.x.0新目录,不会出现目录冲突。 - 如果你需要默认安装路径和旧版本同父目录,可以在
InitializeWizard事件中读取旧版本的安装路径,自动设置全量包的默认安装父目录:
procedure InitializeWizard(); var sUnInstPath: string; sOldInstallLoc: string; sNewDefaultDir: string; begin sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); // 读取旧版本安装路径 if not RegQueryStringValue(HKLM, sUnInstPath, 'InstallLocation', sOldInstallLoc) then RegQueryStringValue(HKCU, sUnInstPath, 'InstallLocation', sOldInstallLoc); if sOldInstallLoc <> '' then begin // 取旧路径的父目录,拼接全量包的新目录名 sNewDefaultDir := ExtractFileDir(sOldInstallLoc) + '\{#MyAppName} {#MyAppVersion}'; WizardForm.DirEdit.Text := sNewDefaultDir; end; end;
注意事项
- 全量包和补丁包必须使用完全相同的
AppId,才能读取到同一条卸载注册表记录 - 重命名目录前确保没有应用进程在运行,避免重命名失败,可以在
ssInstall步骤先杀掉应用进程 - 如果是64位应用,需要在
[Setup]段添加ArchitecturesInstallIn64BitMode=x64,避免注册表重定向导致读取不到卸载项
内容的提问来源于stack exchange,提问作者kzaiwo
相关产品推荐
相关产品推荐

