Search code examples
installationinno-setupuninstallationpascalscript

Waiting for uninstaller prompt in usPostUninstall before proceeding with installation in Inno Setup


Is there any way to pause the execution of Inno Setup until user makes some interactions with the message box. I am using a message box to confirm whether or not to keep user data. I want to stop all other executions in setup until the user selects yes or no.

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usPostUninstall then
  begin
    if DirExists(ExpandConstant('{localappdata}\{#MyBuildId}\storage'))  then
      if MsgBox('Do you want to delete the saved user data?',
        mbConfirmation, MB_YESNO) = IDYES
      then
        DelTree(ExpandConstant('{localappdata}\{#MyBuildId}\storage'), True, True, True);
  end;
end;

I am using a separate procedure to uninstall the previous version in the beginning of the install.

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if (CurStep=ssInstall) then
  begin
    if (IsUpgrade()) then
    begin
      UnInstallOldVersion();
    end;
  end;
end;

So when starting to install a new setup first it uninstalls the old version. The user data deletion message box is also shown. But the execution is not pausing. It uninstalls and reinstalls the app while the message box is showing

function GetUninstallString(): String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath :=
    ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppId}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

function UnInstallOldVersion(): Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
{ Return Values: }
{ 1 - uninstall string is empty }
{ 2 - error executing the UnInstallString }
{ 3 - successfully executed the UnInstallString }

  // default return value
  Result := 0;

  { get the uninstall string of the old app }
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART','', SW_HIDE,
            ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

Solution

  • When you execute the Inno Setup uninstaller .exe, it clones itself to a temporary folder and runs the clone internally. The main process waits for the clone to (almost) finish, before it terminates itself. The clone can then delete the main uninstaller .exe (as it is not locked anymore). The main process is terminated just after the actual uninstallation completes. But before CurUninstallStepChanged(usPostUninstall). So if you display your message box there, the main uninstaller process is terminated already and so is the Exec in UnInstallOldVersion.

    If possible, do the data deletion on usUninstall, not on usPostUninstall.