I have an understanding now of how to use this DswinsHs for downloading a file (as we have it working for my help documentation).
But now I need to migrate some old code that optionally downloaded and installed Dot Net Framework.
I have this code (used ISTool DLL):
const
// Changed to 4.6.2 download link (see: http://msdn.microsoft.com/en-us/library/ee942965%28v=vs.110%29.aspx#redist)
dotnetRedistURL = 'http://go.microsoft.com/fwlink/?LinkId=780600';
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
IsInstalled: Cardinal;
begin
Result := '';
dotNetNeeded := true;
// Check for required netfx installation
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx#net_b
if(Is64BitInstallMode()) then begin
if (RegValueExists(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release')) then begin
RegQueryDWordValue(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', IsInstalled);
if(IsInstalled >= 378675) then begin
dotNetNeeded := false;
downloadNeeded := false;
end;
end;
end
else begin
if (RegValueExists(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release')) then begin
RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', IsInstalled);
if(IsInstalled >= 378675) then begin
dotNetNeeded := false;
downloadNeeded := false;
end;
end;
end;
if(dotNetNeeded) then begin
if (not IsAdminLoggedOn()) then begin
Result := ExpandConstant('{cm:DotNet_NeedAdminRights}');
end
else begin
dotnetRedistPath := ExpandConstant('{src}\NDP451-KB2858728-x86-x64-AllOS-ENU.exe');
if not FileExists(dotnetRedistPath) then begin
dotnetRedistPath := ExpandConstant('{tmp}\NDP451-KB2858728-x86-x64-AllOS-ENU.exe');
if not FileExists(dotnetRedistPath) then begin
isxdl_AddFile(dotnetRedistURL, dotnetRedistPath);
downloadNeeded := true;
end;
end;
if (downloadNeeded) then begin
if (MsgBox(ExpandConstant('{cm:DotNet_NeedToDownload}'), mbConfirmation, MB_OKCANCEL) = IDCANCEL) then begin
Result := ExpandConstant('{cm:DotNet_InstallAborted}');
end;
end;
end;
end;
// AJT v19.0.0 We always delete the existing local help file if it exists.
// The new version will be downloaded on the next wizard form if
// the user still wants the local help. ("downloadhelp" task selected).
if (bDownloadHelpDocSetup) then DoDeleteFile(ExpandConstant('{app}\CommunityTalks.chm'));
end;
Then I have:
procedure CurStepChanged(CurStep: TSetupStep);
var
hWnd: Integer;
ResultCode: Integer;
begin
if (CurStep = ssInstall) then
begin
hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
// Don't try to init isxdl if it's not needed because it will error on < ie 3
if (downloadNeeded) then begin
isxdl_SetOption('label', ExpandConstant('{cm:Downloading}'));
isxdl_SetOption('description', ExpandConstant('{cm:DownloadingInfo}'));
if (isxdl_DownloadFiles(hWnd) = 1) then begin
if (dotNetNeeded = true) then begin
if Exec(ExpandConstant(dotnetRedistPath), '/quiet', '',
SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
// handle success if necessary; ResultCode contains the exit code
if not (ResultCode = 0) then begin
// Microsoft present an array of options for this. But since
// The interface was visible I think it is safe to just say
// that the installation was not completed.
MsgBox(ExpandConstant('{cm:DotNet_InstallFailed}'), mbInformation, MB_OK);
Abort();
end;
end
else begin
// The execution failed for some reason
MsgBox(SysErrorMessage(ResultCode), mbInformation, MB_OK);
Abort();
end;
end;
end
else begin
// The user most likely cancelled the download of the file
MsgBox(ExpandConstant('{cm:DotNet_DownloadFailed}'), mbInformation, MB_OK);
Abort();
end;
end;
end;
end;
That needs changing.
For my download that does work with DwinsHs I basically have two bits as follows:
[Files]
section: ; AJT v19.0.0 Download Help Documentation Setup file.
; This is associated with the "downloadhelp" task.
; It will be downloaded from the internet and deleted after install.
Source: "{tmp}\HelpDocSetup.exe"; \
DestDir: "{app}"; \
Flags: external deleteafterinstall; \
Tasks: downloadhelp; \
Check: DwinsHs_Check( ExpandConstant('{tmp}\HelpDocSetup.exe'), '{#HelpDocSetupURL}', \
'My_Setup', 'Get', {#HelpDocSetupFileSize}, 0 )
[Run]
section: ; AJT v19.0.0 Installed the downloaded help documentation.
; This is only done if the "downloadhelp" task was selected.
Filename: "{app}\HelpDocSetup.exe"; \
Parameters: "/SP- /VERYSILENT /InstallPath=""{app}"""; \
WorkingDir: "{app}"; \
Flags: waituntilterminated runhidden; \
Description: "{cm:InstallingHelpDescription}"; \
StatusMsg: "{cm:InstallingHelpStatusMessage}"; \
Tasks: downloadhelp
I need to convert my previous code (DotNet prerequisite) into suitable file / run script lines (except this time I have to pass 0 for the file size as I do not know the size).
In short, my setup requires admin privileges, and technically, we need it to download and install dotnet (if it is not there) before continuing with the setup. The reason being we have these run entries:
Filename: "{dotnet40}\regasm.exe"; \
Parameters: "PTSTools_x86.dll /codebase"; \
WorkingDir: "{app}"; \
Flags: runhidden
Filename: "{dotnet4064}\regasm.exe"; \
Parameters: "PTSTools_x64.dll /codebase"; \
WorkingDir: "{app}"; \
Flags: runhidden; \
Check: IsWin64
Filename: "{dotnet40}\regasm.exe"; \
Parameters: "/u PTSTools_x86.dll"; \
WorkingDir: "{app}"; \
Flags: runhidden; \
Check: FileExists(ExpandConstant('{app}\PTSTools.dll')); \
AfterInstall: DoDeleteFile(ExpandConstant('{app}\PTSTools.dll'))
Filename: "{dotnet4064}\regasm.exe"; \
Parameters: "/u PTSTools.dll"; \
WorkingDir: "{app}"; \
Flags: runhidden; \
Check: IsWin64 and FileExists(ExpandConstant('{app}\PTSTools.dll')); \
AfterInstall: DoDeleteFile(ExpandConstant('{app}\PTSTools.dll'))
So having DotNet is a prerequisite for the installer to work. Should I be dealing with this differently?
Based on the answer provided and my understanding of the documentation ...
Step 1
In PrepareToInstall
we check to see if DotNet is needed and cache the result:
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
IsInstalled: Cardinal;
begin
Result := '';
dotNetNeeded := true;
// Check for required netfx installation
// http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx#net_b
if(Is64BitInstallMode()) then begin
if (RegValueExists(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release')) then begin
RegQueryDWordValue(HKLM, 'SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', IsInstalled);
if(IsInstalled >= 378675) then begin
dotNetNeeded := false;
end;
end;
end
else begin
if (RegValueExists(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release')) then begin
RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', IsInstalled);
if(IsInstalled >= 378675) then begin
dotNetNeeded := false;
end;
end;
end;
if(dotNetNeeded) then begin
if (MsgBox(ExpandConstant('{cm:DotNet_NeedToDownload}'), mbConfirmation, MB_OKCANCEL) = IDCANCEL) then begin
Result := ExpandConstant('{cm:DotNet_InstallAborted}');
end;
end;
end;
Step 2
We add a BeforeDownload
handler. This is where we get a chance to add the file we need to download to the list:
function BeforeDownload(): Boolean;
begin
if(dotNetNeeded) then
begin
dotNetRedistPath := ExpandConstant('{tmp}\NDP451-KB2858728-x86-x64-AllOS-ENU.exe');
DwinsHs_AppendRemoteFile( dotNetRedistPath, \
dotnetRedistURL, 'My_Setup', rmGet, FILESIZE_QUERY_SERVER );
end;
Result := True;
end;
Step 3
We add a AfterDownload
handler. This is where we perform the install of DotNet.
procedure AfterDownload(State: Integer);
var
hWnd: Integer;
ResultCode: Integer;
begin
if (State = READ_OK) then
begin
if(dotNetNeeded) then
begin
if Exec(ExpandConstant(dotnetRedistPath), '/quiet', '',
SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin
// handle success if necessary; ResultCode contains the exit code
if not (ResultCode = 0) then begin
// Microsoft present an array of options for this. But since
// The interface was visible I think it is safe to just say
// that the installation was not completed.
MsgBox(ExpandConstant('{cm:DotNet_InstallFailed}'), mbInformation, MB_OK);
Abort();
end;
end
else begin
// The execution failed for some reason
MsgBox(SysErrorMessage(ResultCode), mbInformation, MB_OK);
Abort();
end;
end;
end;
end;
I am not sure if "quiet" is the right way to go now ...
Step 4
We adjust the CurPageChanged handler:
procedure CurPageChanged(CurPage: Integer);
begin
DwinsHs_CurPageChanged(CurPage, @BeforeDownload, @AfterDownload);
end;
Just call DwinsHs_AppendRemoteFile
when dotNetNeeded
.
DwinsHs_AppendRemoteFile
has basically the same arguments as DwinsHs_Check
(DwinsHs_Check
is actually only a Check
-compatible wrapper around DwinsHs_AppendRemoteFile
).
I believe that's all you need. The [Run]
happens only after the download.