inno-setup

Install several copies of software by an installer made by Inno Setup


We prepare installers using Inno Setup. So a user installs the software. When new version is released, a new installer updates the software. So far so good.

But some people want to have both old version of the software and new one.

Is it possible to make an installer ask if a user wants to update current installation or install new version side by side.


Solution

  • In InitializeSetup event function, detect if the application is installed already. If it is, ask user, and if he/she chooses to install a new copy, change AppId and DefaultDirName to version-specific values to force a new installation.

    [Setup]
    #define AppId "My Program"
    #define SetupReg \
        "Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppId + "_is1"
    #define DispVerReg "DisplayVersion"
    #define ApplicationVersion() \
       ParseVersion('MyProg.exe', Local[0], Local[1], Local[2], Local[3]), \
       Str(Local[0]) + "." + Str(Local[1])
    
    [Setup]
    AppId={code:GetAppId}
    AppName=My Program
    AppVersion={#ApplicationVersion}
    DefaultDirName={code:GetDefaultDirName}
    UsePreviousLanguage=no
    
    [Files]
    Source: "MyProg.exe"; DestDir: "{app}"
    
    [Code]
    
    var
      AppId: string;
      DefaultDirName: string;
    
    function GetAppId(Param: string): string;
    begin
      Result := AppId;
      Log('AppId = ' + Result);
    end;
    
    function GetDefaultDirName(Param: string): string;
    begin
      Result := DefaultDirName;
      Log('DefaultDirName = ' + Result);
    end;
    
    function InitializeSetup(): Boolean;
    var
      PrevVersion: string;
      CurVersion: string;
      Msg: string;
      R: Integer;
    begin
      CurVersion := '{#ApplicationVersion}';
      Log(Format('Installing "%s"', [CurVersion]));
      Result := True;
    
      AppId := '{#AppId}';
      DefaultDirName := ExpandConstant('{pf}\My Program');
    
      if RegQueryStringValue(HKLM, '{#SetupReg}', '{#DispVerReg}', PrevVersion) or
         RegQueryStringValue(HKCU, '{#SetupReg}', '{#DispVerReg}', PrevVersion) then
      begin
        Msg :=
          Format(
            'Version is %s already installed. Do you want to upgrade to %s?'#13#10 +
            #13#10 +
            'Press Yes, to replace %0:s with %1:s.'#13#10 +
            'Press No, to keep %0:s and add separate installation of %1:s.'#13#10, [
            PrevVersion, CurVersion]);
        R := MsgBox(Msg, mbConfirmation, MB_YESNOCANCEL);
        if R = IDYES then
        begin
          Log('User chose to replace previous installation');
        end
          else
        if R = IDNO then
        begin
          AppId := AppId + CurVersion;
          DefaultDirName := DefaultDirName + ' ' + CurVersion;
          Log('User chose to install new copy - using ID ' + AppId);
        end
          else
        begin
          Log('User chose to cancel installation');
          Result := False;
        end;
      end;
    end;
    

    enter image description here


    And of course, this is installation part only. Your application must be able to somehow separate configurations for the separate installation instances.