3

In case of an upgrade / re-installation, is there a way to discard the /TYPE and /COMPONENTS parameter value passed on the command line to the installer and instead use the previously used values ? I can read the values used earlier from Registry (or alternatively make out the details based on existence of files assuming they have not been manually altered)

I have read the following threads and can disable the "Select Components" page in UI mode

  1. Inno Setup Skip "Select Components" page when /Type command-line parameter is specified
  2. InnoSetup: Disable components page on upgrade

However, if the aforesaid parameters are passed from command line, they seem to override the defaults.

Anand
  • 473
  • 3
  • 14

1 Answers1

2

You cannot discard them.

What you can do is to check if those parameters were provided and if they were:

  • Re-launch the installer without them (show below), or
  • Read the previously selected type and components from registry and re-set the controls accordingly.

Re-launching the installer without /TYPE= and /COMPONENTS=

const
  UninstallKey =
    'Software\Microsoft\Windows\CurrentVersion\Uninstall\' +
    '{#SetupSetting("AppId")}_is1';

function IsUpgrade: Boolean;
var
  Value: string;
begin
  Result :=
    (RegQueryStringValue(HKLM, UninstallKey, 'UninstallString', Value) or
     RegQueryStringValue(HKCU, UninstallKey, 'UninstallString', Value)) and
    (Value <> '');
end;

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): THandle;
  external 'ShellExecuteW@shell32.dll stdcall';
  
function InitializeSetup(): Boolean;
var
  Params, S: string;
  Relaunch: Boolean;
  I, RetVal: Integer;
begin
  Result := True;

  if IsUpgrade then
  begin
    Relaunch := False;
    // Collect current instance parameters
    for I := 1 to ParamCount do
    begin
      S := ParamStr(I);
      if (CompareText(Copy(S, 1, 7), '/TYPES=') = 0) or
         (CompareText(Copy(S, 1, 12), '/COMPONENTS=') = 0) then
      begin
        Log(Format('Will re-launch due to %s', [S]));
        Relaunch := True;
      end
        else
      begin
        // Unique log file name for the child instance
        if CompareText(Copy(S, 1, 5), '/LOG=') = 0 then
        begin
          S := S + '-sub';
        end;
        // Do not pass our /SL5 switch
        // This should not be needed since Inno Setup 6.2,
        // see https://groups.google.com/g/innosetup/c/pDSbgD8nbxI
        if CompareText(Copy(S, 1, 5), '/SL5=') <> 0 then
        begin
          Params := Params + AddQuotes(S) + ' ';
        end;
      end;
    end;

    if not Relaunch then
    begin
      Log('No need to re-launch');
    end
      else
    begin
     Log(Format('Re-launching setup with parameters [%s]', [Params]));
      RetVal :=
        ShellExecute(0, '', ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
      Log(Format('Re-launching setup returned [%d]', [RetVal]));
      Result := (RetVal > 32);
      // if re-launching of this setup succeeded, then...
      if Result then
      begin
        Log('Re-launching succeeded');
        // exit this setup instance
        Result := False;
      end
        else
      begin
        Log(Format('Elevation failed [%s]', [SysErrorMessage(RetVal)]));
      end;
    end;
  end;
end;

The code is for Unicode version of Inno Setup.

The code can be further improved to keep the master installer waiting for the child installer to complete. When can make a difference, particularly if the installer is executed by some automatic deployment process.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992