TomCat500
TomCat500

Reputation: 174

Inno Setup: Overwrite existing installation or show dir prompt

It would be nice if I have this in my setup:

Is it possible to use existing Inno Setup options to achieve this? Or do I have to build a custom dialog page?

Upvotes: 3

Views: 3045

Answers (2)

Martin Prikryl
Martin Prikryl

Reputation: 202088

At the beginning (InitializeSetup event function), check if the application is installed already (see GetUninstallString in the code below). If it is, ask user, what to do (see MsgBox use in the code and the first screenshot). If user chooses to update the existing installation, proceed normally. Inno Setup by default does not allow changing installation path of an existing installation (see DisableDirPage).

If uses chooses to install another copy, set AppId to a new unique value (GetAppId function in the code). This will make Inno Setup treat the installation as new, so it will prompt for the installation path. Update also UninstallDisplayName, so that the user can distinguish the installations when choosing which copy to uninstall (see GetAppIdentification and the third screenshot). Also update DefaultDirName to a new unique path (see GetAppIdentification and the third screenshot).

#define AppName "My Program"
#define AppVersion "1.5"

[Setup]
AppId={code:GetAppId}
AppName={#AppName}
AppVersion={#AppVersion}
UninstallDisplayName={#AppName} {#AppVersion}{code:GetAppIdentification}
UsePreviousLanguage=no # Needed when AppId is dynamic
DefaultDirName={autopf}\My Program{code:GetAppIdentification}
[Code]

var
  Instance: string;

function GetAppId(Param: string): string;
begin
  Result := '{#AppName}' + Instance;
end;

function GetAppIdentification(Param: string): string;
begin
  if Instance <> '' then Result := ' (' + Instance + ')';
end;

function GetUninstallString(): string;
var
  UninstallKey: string;
begin
  UninstallKey :=
    'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + GetAppId('') + '_is1';
  RegQueryStringValue(HKA, UninstallKey, 'UninstallString', Result);
  Log(Result)
end;

function InitializeSetup(): Boolean;
var
  Message: string;
  Answer: Integer;
begin
  Result := True;
  if GetUninstallString() = '' then
  begin
    Log('Application is not installed yed, installing the first copy');
  end
    else
  begin
    Log('Application is installed already, asking what to do');
    Message :=
      'This program is installed already, ' +
      'do you want to update the existing installation? ' +
      'Press No to install another copy of the program';
    Answer := MsgBox(Message, mbConfirmation, MB_YESNOCANCEL);
    if Answer = IDYES then
    begin
      Log('User chose to update the installation');
    end
      else
    if Answer = IDNO then
    begin
      Log('User chose to install another copy');
      Instance := '2';
    end
      else
    begin
      Log('User chose to abort the installation');
      Result := False;
    end;
  end;
end;

enter image description here

enter image description here

enter image description here


Now the question is what to do if there are already two installations. To make a third (or more), it's easy, just loop, increasing the value in Instance, until GetUninstallString returns an empty string. But had you wanted the user to be able to choose what copy to update, it would be more difficult. That's too much for one question.


What you want to do is quite complicated. If you want to keep the flexibility, I think that the easiest solution is to treat every new version as a separate software. In addition, when starting the installation, as a courtesy to those who want to keep the latest version only, offer to uninstall the previous (latest) installation automatically. If the user already has multiple installations, do nothing specific (or just inform the user).

Upvotes: 3

Bill_Stewart
Bill_Stewart

Reputation: 24515

I solved this problem by putting the responsibility on the user (the one installing the application) to explicitly specify that they want to install a separate instance of the application by specifying a /instancename parameter on the installer's command line (the AppId directive uses a scripted constant).

Upvotes: 1

Related Questions