在 Inno Setup 安装程序中,卸载由 InstallShield LE 进行的安装

In Inno Setup installer, uninstall installation made by InstallShield LE

由于 VS 2017 不支持 InstallShield LE,我尝试改用 Inno Setup。

但是如何在使用 Inno Setup 脚本开始安装之前卸载之前由 InstallShield LE 进行的安装。
不同用户(不在同一台计算机上)安装了多个版本的应用程序。

由于版本之间的产品代码不同,Uninstall 注册表项中的 GUID 可能不同,因此很难在注册表的卸载部分找到。

当我编写示例脚本和 the related blog post 时,很明显您应该查询注册表以检测以前安装的软件,

function InitializeSetup(): Boolean;
var
  oldVersion: String;
  uninstaller: String;
  ErrorCode: Integer;
begin
  if RegKeyExists(HKEY_LOCAL_MACHINE,
    'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1') then
  begin
    RegQueryStringValue(HKEY_LOCAL_MACHINE,
      'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1',
      'DisplayVersion', oldVersion);
    if (CompareVersion(oldVersion, '6.0.0.1004') < 0) then
    begin
      if MsgBox('Version ' + oldVersion + ' of Code Beautifier Collection is already installed. Continue to use this old version?',
        mbConfirmation, MB_YESNO) = IDYES then
      begin
        Result := False;
      end
      else
      begin
          RegQueryStringValue(HKEY_LOCAL_MACHINE,
            'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1',
            'UninstallString', uninstaller);
          ShellExec('runas', uninstaller, '/SILENT', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
          Result := True;
      end;
    end
    else
    begin
      MsgBox('Version ' + oldVersion + ' of Code Beautifier Collection is already installed. This installer will exit.',
        mbInformation, MB_OK);
      Result := False;
    end;
  end
  else
  begin
    Result := True;
  end;
end;

您的基于 InstallShield 的安装程序还应将基于 GUID 的子树插入到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\,因此只需分析其中的内容并采取必要的操作将其卸载。

A more recent blog post can be found here.

您可以使用 Inno Setup: How to automatically uninstall previous installed version?

中的代码

虽然答案中的代码用于卸载由 Inno Setup 安装的以前的版本,但它基本上足够通用,可以与任何以前的卸载系统一起使用。

要使其与 InstallShield 一起使用,您需要知道要卸载的版本的产品代码。如果您需要能够删除任何版本,您可以使用升级代码查找实际安装版本的产品代码。为此,您可以使用 WMI 查询:
How to find the UpgradeCode and ProductCode of an installed application in Windows 7.

在 Inno Setup Pascal 脚本中,代码可以是这样的:

const
  InstallShieldUpgradeCode = '{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}';

function InitializeSetup(): Boolean;
var
  WbemLocator, WbemServices, WbemObjectSet: Variant;
  Query: string;
  ProductCode: string;
begin
  WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  WbemServices := WbemLocator.ConnectServer('.', 'root\CIMV2');
  Query :=
    'SELECT ProductCode FROM Win32_Property ' +
    'WHERE Property="UpgradeCode" AND Value="' + InstallShieldUpgradeCode + '"';
  WbemObjectSet := WbemServices.ExecQuery(Query);
  if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
  begin
    ProductCode := WbemObjectSet.ItemIndex(0).ProductCode;

    { Start uninstall here }
  end;

  Result := True;
end;

但请注意,查询可能需要数十秒。