I need to install some system prerequisites and after finalizing them restart the system, then it must continue the installation where I left off. The prerequisites are .NET framework and an update of Windows.
My [Code]
section:
const
(*** Customize the following to your own name. ***)
RunOnceName = 'My Program Setup restart';
QuitMessageReboot = 'Os requisitos para a instalação do sistema não estão completos. Precisamos reiniciar seu computador para continuar a instalação do sistema.'#13#13'Depois de reiniciar o seu computador, o setup irá continuar a instalação após o primeiro login com uma conta administradora.';
QuitMessageError = 'Error. Cannot continue.';
var
Restarted: Boolean;
ResultCode: Integer;
function InitializeSetup(): Boolean;
begin
Restarted := ExpandConstant('{param:restart|0}') = '1';
if not Restarted then begin
Result := not RegValueExists(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName);
if not Result then
MsgBox(QuitMessageReboot, mbError, mb_Ok);
end else
Result := True;
end;
function DetectAndInstallPrerequisites: Boolean;
begin
(*** Place your prerequisite detection and installation code below. ***)
(*** Return False if missing prerequisites were detected but their installation failed, else return True. ***)
if not Exec(ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
MsgBox(QuitMessageReboot + IntToStr(ResultCode) + '....',
mbError, MB_OK);
end;
Result := True;
end;
function Quote(const S: String): String;
begin
Result := '"' + S + '"';
end;
function AddParam(const S, P, V: String): String;
begin
if V <> '""' then
Result := S + ' /' + P + '=' + V;
end;
function AddSimpleParam(const S, P: String): String;
begin
Result := S + ' /' + P;
end;
procedure CreateRunOnceEntry;
var
RunOnceData: String;
begin
RunOnceData := Quote(ExpandConstant('{srcexe}')) + ' /restart=1';
RunOnceData := AddParam(RunOnceData, 'LANG', ExpandConstant('{language}'));
RunOnceData := AddParam(RunOnceData, 'DIR', Quote(WizardDirValue));
RunOnceData := AddParam(RunOnceData, 'GROUP', Quote(WizardGroupValue));
if WizardNoIcons then
RunOnceData := AddSimpleParam(RunOnceData, 'NOICONS');
RunOnceData := AddParam(RunOnceData, 'TYPE', Quote(WizardSetupType(False)));
RunOnceData := AddParam(RunOnceData, 'COMPONENTS', Quote(WizardSelectedComponents(False)));
RunOnceData := AddParam(RunOnceData, 'TASKS', Quote(WizardSelectedTasks(False)));
(*** Place any custom user selection you want to remember below. ***)
//<your code here>
RegWriteStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName, RunOnceData);
end;
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ChecksumBefore, ChecksumAfter: String;
begin
ChecksumBefore := MakePendingFileRenameOperationsChecksum;
if DetectAndInstallPrerequisites then begin
ChecksumAfter := MakePendingFileRenameOperationsChecksum;
if ChecksumBefore <> ChecksumAfter then begin
CreateRunOnceEntry;
NeedsRestart := True;
Result := QuitMessageReboot;
end;
end else
Result := QuitMessageError;
end;
function ShouldSkipPage(PageID: Integer): Boolean;
begin
Result := Restarted;
end;
The return is the variable QuitMessageReboot
concatenated with the ResultCode
that has the value 2
.
The dotNetFx40_Full_x86_x64.exe
is installed by:
[Files]
;.Net Framework
Source: "Dependencias\.Net Framework\dotNetFx40_Full_x86_x64.exe"; DestDir: "{tmp}"; \
Flags: deleteafterinstall
As the name says, the PrepareToInstall
event happens before the installation. The files are not installed yet. So the Exec
obviously fails, as there's nothing to execute.
You can extract the dotNetFx40_Full_x86_x64.exe
from the code using ExtractTemporaryFile
function:
[Files]
Source: "...\dotNetFx40_Full_x86_x64.exe"; Flags: dontcopy
[Code]
function DetectAndInstallPrerequisites: Boolean;
var
ResultCode: Integer;
Success: Boolean;
begin
ExtractTemporaryFile('dotNetFx40_Full_x86_x64.exe');
WizardForm.PreparingLabel.Caption := 'Installing .NET framework...';
WizardForm.PreparingLabel.Visible := True;
try
Success :=
Exec(
ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe'), '/q /norestart', '',
SW_SHOW, ewWaitUntilTerminated, ResultCode);
finally
WizardForm.PreparingLabel.Caption := '';
WizardForm.PreparingLabel.Visible := False;
end;
if not Success then
...
end;
Make sure you add the dontcopy
flag to the [Files]
section entry.