Update an InnoSetup Installation - Update Previous Install Dir

Viewed 97

I am creating installers for either full application and patch.

For the full app installer (300MB+), versioning is x.x.0 (ex. 1.1.0). And for the patch (10MB+) it is x.x.x (ex. 1.1.1).

The installation folder is formatted like this: "App Name ". Example - App Name 1.1.0, App Name 1.1.1

There should only be 1 version of the app that resides in the machine, so for full version installs - when the app is detected to be previously installed, the existing app is uninstalled first.

So the scenario is like this:

  1. User installs a full app - 1.1.0 (OK)
    • Directory App Name 1.1.0 is created
  2. User installs a patch - 1.1.1 (OK)
    • UsePreviousAppDir=true so it writes on top of directory App Name 1.1.0
    • App Name 1.1.0 is renamed to App Name 1.1.1 as part of CurStepChanged() when CurStep is ssPostInstall.
  3. User installs a full app - 1.2.0 (NOK - expected to uninstall the prev version 1.1.1 and install this new version 1.2.0)
    • If UsePreviousAppDir is true, directory App Name 1.1.0 is created. This is because this is what Innosetup remembers as the "previous app" (since we only renamed the patch).
    • If UsePreviousAppDir is false, directory App Name 1.2.0 is created. And the prev version App Name 1.1.1 is not uninstalled because the previous install was pointing to App Name 1.1.0.

How can I configure my ISS file so that when I do a full install after a patch install, it can still find the renamed directory and uninstall it?

For reference, here is my code for renaming in patch installer:

{ ///////////////////////////////////////////////////////////////////// }
procedure CurStepChanged(CurStep: TSetupStep);
begin
   if (CurStep=ssPostInstall) then begin
    RenameFile(ExpandConstant('{app}'), ExpandConstant('{app}\..\{#MyAppName} {#MyAppVersion}'))     
    end;
end;

And for my uninstall script (full version):

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


{ ///////////////////////////////////////////////////////////////////// }
function IsUpgrade(): Boolean;
begin
  Result := (GetUninstallString() <> '');
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 /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;

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

And my [UninstallDelete] section in the patch installer, in case user wants to uninstall the entire thing:

[UninstallDelete]
Type: filesandordirs; Name: "{app}\..\{#MyAppName} {#MyAppVersion}"

Thanks!

0 Answers
Related