From fc4f64feef65dbb87a9f48ef04760d1967ee7e97 Mon Sep 17 00:00:00 2001 From: Timo Schwarzer Date: Tue, 9 Jul 2024 18:38:13 +0200 Subject: [PATCH] Download and install vc++ runtime if missing/outdated --- dependencies.iss | 231 +++++++++++++++++++++++++++++++++++++++++++++++ setup.iss | 8 ++ 2 files changed, 239 insertions(+) create mode 100644 dependencies.iss diff --git a/dependencies.iss b/dependencies.iss new file mode 100644 index 0000000..274e710 --- /dev/null +++ b/dependencies.iss @@ -0,0 +1,231 @@ +[Code] +// Fork of https://github.com/DomGries/InnoDependencyInstaller + +// types and variables +type + TDependency_Entry = record + Filename: String; + Parameters: String; + Title: String; + URL: String; + Checksum: String; + ForceSuccess: Boolean; + RestartAfter: Boolean; + end; + +var + Dependency_Memo: String; + Dependency_List: array of TDependency_Entry; + Dependency_NeedToRestart, Dependency_ForceX86: Boolean; + Dependency_DownloadPage: TDownloadWizardPage; + +procedure Dependency_Add(const Filename, Parameters, Title, URL, Checksum: String; const ForceSuccess, RestartAfter: Boolean); +var + Dependency: TDependency_Entry; + DependencyCount: Integer; +begin + Dependency_Memo := Dependency_Memo + #13#10 + '%1' + Title; + + Dependency.Filename := Filename; + Dependency.Parameters := Parameters; + Dependency.Title := Title; + + if FileExists(ExpandConstant('{tmp}{\}') + Filename) then begin + Dependency.URL := ''; + end else begin + Dependency.URL := URL; + end; + + Dependency.Checksum := Checksum; + Dependency.ForceSuccess := ForceSuccess; + Dependency.RestartAfter := RestartAfter; + + DependencyCount := GetArrayLength(Dependency_List); + SetArrayLength(Dependency_List, DependencyCount + 1); + Dependency_List[DependencyCount] := Dependency; +end; + + +procedure Dependency_InitializeWizard; +begin + Dependency_DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil); +end; + + +function Dependency_PrepareToInstall(var NeedsRestart: Boolean): String; +var + DependencyCount, DependencyIndex, ResultCode: Integer; + Retry: Boolean; + TempValue: String; +begin + DependencyCount := GetArrayLength(Dependency_List); + + if DependencyCount > 0 then begin + Dependency_DownloadPage.Show; + + for DependencyIndex := 0 to DependencyCount - 1 do begin + if Dependency_List[DependencyIndex].URL <> '' then begin + Dependency_DownloadPage.Clear; + Dependency_DownloadPage.Add(Dependency_List[DependencyIndex].URL, Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Checksum); + + Retry := True; + while Retry do begin + Retry := False; + + try + Dependency_DownloadPage.Download; + except + if Dependency_DownloadPage.AbortedByUser then begin + Result := Dependency_List[DependencyIndex].Title; + DependencyIndex := DependencyCount; + end else begin + case SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of + IDABORT: begin + Result := Dependency_List[DependencyIndex].Title; + DependencyIndex := DependencyCount; + end; + IDRETRY: begin + Retry := True; + end; + end; + end; + end; + end; + end; + end; + + if Result = '' then begin + for DependencyIndex := 0 to DependencyCount - 1 do begin + Dependency_DownloadPage.SetText(Dependency_List[DependencyIndex].Title, ''); + Dependency_DownloadPage.SetProgress(DependencyIndex + 1, DependencyCount + 1); + + while True do begin + ResultCode := 0; +#ifdef Dependency_CustomExecute + if {#Dependency_CustomExecute}(ExpandConstant('{tmp}{\}') + Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Parameters, ResultCode) then begin +#else + if ShellExec('', ExpandConstant('{tmp}{\}') + Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then begin +#endif + if Dependency_List[DependencyIndex].RestartAfter then begin + if DependencyIndex = DependencyCount - 1 then begin + Dependency_NeedToRestart := True; + end else begin + NeedsRestart := True; + Result := Dependency_List[DependencyIndex].Title; + end; + break; + end else if (ResultCode = 0) or Dependency_List[DependencyIndex].ForceSuccess then begin // ERROR_SUCCESS (0) + break; + end else if ResultCode = 1641 then begin // ERROR_SUCCESS_REBOOT_INITIATED (1641) + NeedsRestart := True; + Result := Dependency_List[DependencyIndex].Title; + break; + end else if ResultCode = 3010 then begin // ERROR_SUCCESS_REBOOT_REQUIRED (3010) + Dependency_NeedToRestart := True; + break; + end; + end; + + case SuppressibleMsgBox(FmtMessage(SetupMessage(msgErrorFunctionFailed), [Dependency_List[DependencyIndex].Title, IntToStr(ResultCode)]), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of + IDABORT: begin + Result := Dependency_List[DependencyIndex].Title; + break; + end; + IDIGNORE: begin + break; + end; + end; + end; + + if Result <> '' then begin + break; + end; + end; + + if NeedsRestart then begin + TempValue := '"' + ExpandConstant('{srcexe}') + '" /restart=1 /LANG="' + ExpandConstant('{language}') + '" /DIR="' + WizardDirValue + '" /GROUP="' + WizardGroupValue + '" /TYPE="' + WizardSetupType(False) + '" /COMPONENTS="' + WizardSelectedComponents(False) + '" /TASKS="' + WizardSelectedTasks(False) + '"'; + if WizardNoIcons then begin + TempValue := TempValue + ' /NOICONS'; + end; + RegWriteStringValue(HKA, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', '{#SetupSetting("AppName")}', TempValue); + end; + end; + + Dependency_DownloadPage.Hide; + end; +end; + +#ifndef Dependency_NoUpdateReadyMemo + +#endif +function Dependency_UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String; +begin + Result := ''; + if MemoUserInfoInfo <> '' then begin + Result := Result + MemoUserInfoInfo + Newline + NewLine; + end; + if MemoDirInfo <> '' then begin + Result := Result + MemoDirInfo + Newline + NewLine; + end; + if MemoTypeInfo <> '' then begin + Result := Result + MemoTypeInfo + Newline + NewLine; + end; + if MemoComponentsInfo <> '' then begin + Result := Result + MemoComponentsInfo + Newline + NewLine; + end; + if MemoGroupInfo <> '' then begin + Result := Result + MemoGroupInfo + Newline + NewLine; + end; + if MemoTasksInfo <> '' then begin + Result := Result + MemoTasksInfo; + end; + + if Dependency_Memo <> '' then begin + if MemoTasksInfo = '' then begin + Result := Result + SetupMessage(msgReadyMemoTasks); + end; + Result := Result + FmtMessage(Dependency_Memo, [Space]); + end; +end; + + +function Dependency_NeedRestart: Boolean; +begin + Result := Dependency_NeedToRestart; +end; + +function Dependency_IsX64: Boolean; +begin + Result := not Dependency_ForceX86 and Is64BitInstallMode; +end; + +function Dependency_String(const x86, x64: String): String; +begin + if Dependency_IsX64 then begin + Result := x64; + end else begin + Result := x86; + end; +end; + +function Dependency_ArchSuffix: String; +begin + Result := Dependency_String('', '_x64'); +end; + +function Dependency_ArchTitle: String; +begin + Result := Dependency_String(' (x86)', ' (x64)'); +end; + +procedure Dependency_AddVCppRuntime; +begin + // https://docs.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist + if not IsMsiProductInstalled(Dependency_String('{65E5BD06-6392-3027-8C26-853107D3CF1A}', '{36F68A90-239C-34DF-B58C-64B30153CE35}'), PackVersionComponents(14, 40, 33810, 0)) then begin + Dependency_Add('vcredist2022' + Dependency_ArchSuffix + '.exe', + '/passive /norestart', + 'Visual C++ 2015-2022 Redistributable' + Dependency_ArchTitle, + Dependency_String('https://aka.ms/vs/17/release/vc_redist.x86.exe', 'https://aka.ms/vs/17/release/vc_redist.x64.exe'), + '', False, False); + end; +end; \ No newline at end of file diff --git a/setup.iss b/setup.iss index 1b03ed4..f684026 100644 --- a/setup.iss +++ b/setup.iss @@ -10,6 +10,8 @@ #define MyAppAssocExt ".wotwr" #define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt +#include "dependencies.iss" + [Setup] ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) @@ -46,6 +48,12 @@ Source: "C:\moon\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs creat ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Code] +function InitializeSetup: Boolean; +begin + Dependency_AddVCppRuntime; + Result := True; +end; + procedure DeleteWithRetry; var FileName: string;