Hugo_vdms
Hugo_vdms

Reputation: 65

How to restart Inno Setup installer based on result of procedure that executes a program/subinstaller

I have an install procedure that is executed if the sub exe is not installed, and if so, I want the final "lauch my app" checkbox at the end to be replaced by a "restart computer" checkbox.

How can I do that?

I tried to use the NeedRestart() and also use a global boolean variable. But I can't seem to make it work.

Minimal reproductible example:

the file line :

[Files] 
Source: "Dependencies\ndp48-x86-x64-allos-enu.exe"; \
    DestDir: "{app}"; Flags: deleteafterinstall; \
    AfterInstall: InstallNETFramework; Check: NETFrameworkIsNotInstalled

The installation procedure:

procedure InstallNETFramework;
var
  ResultCode: Integer;
  StatusText: string;
begin
  StatusText := WizardForm.StatusLabel.Caption;
  WizardForm.StatusLabel.Caption := 'Installing .NET Framework 4.8...';
  WizardForm.ProgressGauge.Style := npbstMarquee;
  try
    if not ShellExec('open', ExpandConstant('{app}\ndp48-x86-x64-allos-enu.exe'), '/norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) 
    then
    begin
      MsgBox('.NET Framework 4.8 Installation did not succeed : ' + IntToStr(ResultCode) + '.', mbError, MB_OK);
    end;
  finally
    WizardForm.StatusLabel.Caption := StatusText;
    WizardForm.ProgressGauge.Style := npbstNormal;
  end;
end;

The NeedToRestart event function:

[Code]
var NeedToRestart: boolean;

function NeedToRestart();
begin
//??
end;

If this installation procedure is executed, then at the end, instead of having a "launch {{app}}" I want "restart computer". If possible with the option now or later? It's fine if not.

Upvotes: 2

Views: 379

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202584

As you correctly assumed:

  • introduce a global Boolean variable
  • set it when the .NET installer is successfully executed (you should check ResultCode to be really sure that it did)
  • and use the variable in the NeedRestart event function:
var
  RestartNeeded: Boolean;

function NeedRestart(): Boolean;
begin
  Result := RestartNeeded;
end;

procedure InstallNETFramework;
var
  ResultCode: Integer;
begin
  // ...
  if Exec(ExpandConstant('{app}\ndp48-x86-x64-allos-enu.exe'),
          '/norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) and
     (ResultCode = { whatever success exit code[s] the installer uses }) then
  begin
    Log('.NET Framework 4.8 installation succeeded, need restart');
    RestartNeeded := True;
    // Or if the installer has specific code to indicate success with restart:
    // RestartNeeded := (ResultCode = RestartCode);
  end
    else
  begin
    MsgBox('.NET Framework 4.8 installation did not succeed: ' +
             IntToStr(ResultCode) + '.', mbError, MB_OK);
  end;
  // ...
end;

.NET installer return codes seem to be documented here (but I didn't test it):
https://learn.microsoft.com/en-us/dotnet/framework/deployment/deployment-guide-for-developers#return-codes


Similar question: Inno Setup and VC Redistributable and handling exit code 3010 gracefully


As hinted by @PMF in your other question, as alternative approach might be to try the RestartIfNeededByRun directive along with running your subinstaller using [Run]. Though that limits error handling.

If you want to keep executing (and checking) the .NET installation in code, you can use MakePendingFileRenameOperationsChecksum function:

var
  ResultCode: Integer;
  Checksum: string;
  // ...
  Checksum := MakePendingFileRenameOperationsChecksum;
  if Exec(ExpandConstant('{app}\ndp48-x86-x64-allos-enu.exe'),
          '/norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) and
     (ResultCode = { whatever success exit code[s] the installer uses }) then
  begin
    Log('.NET Framework 4.8 installation succeeded, need restart');
    if Checksum <> MakePendingFileRenameOperationsChecksum then
    begin
      Log('Need to restart detected');
      RestartNeeded := True;
    end;
  end
  // ...

Upvotes: 3

Related Questions