2
votes

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

  • If there is no previous installation, then an edit field for the destination directory should be shown.
  • If there is a previous installation, than the user should should be asked if he wants to overwrite the existing installation (no directory prompt should be visible) or if he wants to install this version in a different directory as a separate installation (two entries in the uninstall list). If this option is chosen, than the edit field for the destination directory should be shown.

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

2

2 Answers

3
votes

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).

1
votes

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).