如何用Inno Setup主卸载程序批量卸载多个子程序?
实现主卸载程序自动卸载所有子应用的方案
完全可以实现这个需求,核心思路是在主安装过程中记录每个已安装子应用的卸载命令,然后在主卸载时依次执行这些命令。以下是针对你的场景的具体实现步骤和修改后的.iss代码:
1. 关键实现逻辑
- 安装阶段:子应用安装完成后,从系统注册表(或子应用自身的卸载信息)中提取卸载命令,保存到主程序的配置文件或注册表中,同时关联对应的组件(确保只卸载用户实际安装的子应用)。
- 卸载阶段:读取保存的卸载命令列表,逐个调用子应用的卸载程序,使用静默参数实现自动卸载。
2. 修改后的主安装程序.iss代码
#define MyAppName "MasterInstaller" #define MyAppVersion "1900.1.11" #define MyAppPublisher "Myself" ; 替换为实际子安装程序的AppId #define WpfAppAppId "{WPF-APP-UNIQUE-ID}" #define WinFormsAppAppId "{WINFORMS-APP-UNIQUE-ID}" [Setup] AppId={{C0CBD111-111A-11B1-111A-965A8921F38A}} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} DefaultDirName=C:\Desktop\test\{#MyAppName} DisableDirPage=no DisableProgramGroupPage=yes Compression=lzma SolidCompression=yes OutputBaseFilename=MasterInstaller PrivilegesRequired=admin [Types] Name: "custom"; Description: "Custom installation"; Flags: iscustom [Components] Name: WpfApp; Description: "WpfApp"; Types: custom Name: WinFormsApp; Description: "WinFormsApp"; Types: custom [Files] Source: "C:\Desktop\innoscripts\WpfAppInstaller.exe"; DestDir: "{app}"; Components: WpfApp; Flags: deleteafterinstall Source: "C:\Desktop\innoscripts\WinFormsAppInstaller.exe"; DestDir: "{app}"; Components: WinFormsApp; Flags: deleteafterinstall [Run] Filename: "{app}\WpfAppInstaller.exe"; Parameters: "/verysilent /DIR={app}\WpfApp"; Flags: waituntilterminated skipifdoesntexist; StatusMsg: "Installing WpfApp"; Components: WpfApp Filename: "{app}\WinFormsAppInstaller.exe"; Parameters: "/verysilent /DIR={app}\WinFormsApp"; Flags: waituntilterminated skipifdoesntexist; StatusMsg: "Installing WinFormsApp..."; Components: WinFormsApp [Code] const UninstallListFile = 'uninstall_list.ini'; procedure SaveUninstallCommand(AppId: string; ComponentName: string); var UninstallKey: string; UninstallString: string; IniPath: string; begin // 查找子应用的卸载注册表项(先查HKLM,再查HKCU) UninstallKey := 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + AppId + '_is1'; if not RegQueryStringValue(HKLM, UninstallKey, 'UninstallString', UninstallString) then RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', UninstallString); if UninstallString <> '' then begin IniPath := ExpandConstant('{app}\') + UninstallListFile; WriteIniString('Uninstalls', ComponentName, UninstallString, IniPath); end; end; procedure CurStepChanged(CurStep: TSetupStep); begin if CurStep = ssPostInstall then begin // 仅保存已安装组件的卸载命令 if IsComponentSelected('WpfApp') then SaveUninstallCommand('{#WpfAppAppId}', 'WpfApp'); if IsComponentSelected('WinFormsApp') then SaveUninstallCommand('{#WinFormsAppAppId}', 'WinFormsApp'); end; end; procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); var IniPath: string; Components: TStringList; I: Integer; UninstallCmd: string; begin if CurUninstallStep = usUninstall then begin IniPath := ExpandConstant('{app}\') + UninstallListFile; if FileExists(IniPath) then begin Components := TStringList.Create; try GetIniSection('Uninstalls', Components, IniPath); for I := 0 to Components.Count - 1 do begin UninstallCmd := ReadIniString('Uninstalls', Components[I], '', IniPath); if UninstallCmd <> '' then begin // 添加静默卸载参数(根据子安装程序实际支持参数调整) UninstallCmd := UninstallCmd + ' /verysilent /norestart'; Exec(UninstallCmd, '', '', SW_HIDE, ewWaitUntilTerminated, nil); end; end; finally Components.Free; DeleteFile(IniPath); end; end; end; end;
3. 注意事项
- 子应用AppId替换:必须将代码中的
{WPF-APP-UNIQUE-ID}和{WINFORMS-APP-UNIQUE-ID}替换为对应子安装程序[Setup]段的AppId值。 - 静默参数适配:如果子应用不是Inno Setup制作的,需替换为该安装程序支持的静默卸载参数(如
/quiet、/uninstall /silent等)。 - 权限保障:主安装程序需以管理员权限运行(
PrivilegesRequired=admin),避免卸载时因权限不足失败。 - 路径无需额外指定:子卸载程序会自行读取自身的安装位置,无需在卸载命令中重复指定路径。
内容的提问来源于stack exchange,提问作者pfinferno
相关产品推荐
相关产品推荐

