dotnet.iss 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. [Setup]
  2. MinVersion=6.1sp1
  3. // remove next line if you only deploy 32-bit binaries and dependencies
  4. ArchitecturesInstallIn64BitMode=x64
  5. // dependency installation requires ready page and ready memo to be enabled (default behaviour)
  6. DisableReadyPage=no
  7. DisableReadyMemo=no
  8. // shared code for installing the dependencies
  9. [Code]
  10. // types and variables
  11. type
  12. TDependency = record
  13. Filename: String;
  14. Parameters: String;
  15. Title: String;
  16. URL: String;
  17. Checksum: String;
  18. ForceSuccess: Boolean;
  19. InstallClean: Boolean;
  20. RebootAfter: Boolean;
  21. end;
  22. InstallResult = (InstallSuccessful, InstallRebootRequired, InstallError);
  23. var
  24. MemoInstallInfo: String;
  25. Dependencies: array of TDependency;
  26. DelayedReboot, ForceX86: Boolean;
  27. DownloadPage: TDownloadWizardPage;
  28. procedure AddDependency(const Filename, Parameters, Title, URL, Checksum: String; const ForceSuccess, InstallClean, RebootAfter: Boolean);
  29. var
  30. Dependency: TDependency;
  31. I: Integer;
  32. begin
  33. MemoInstallInfo := MemoInstallInfo + #13#10 + '%1' + Title;
  34. Dependency.Filename := Filename;
  35. Dependency.Parameters := Parameters;
  36. Dependency.Title := Title;
  37. if FileExists(ExpandConstant('{tmp}{\}') + Filename) then begin
  38. Dependency.URL := '';
  39. end else begin
  40. Dependency.URL := URL;
  41. end;
  42. Dependency.Checksum := Checksum;
  43. Dependency.ForceSuccess := ForceSuccess;
  44. Dependency.InstallClean := InstallClean;
  45. Dependency.RebootAfter := RebootAfter;
  46. I := GetArrayLength(Dependencies);
  47. SetArrayLength(Dependencies, I + 1);
  48. Dependencies[I] := Dependency;
  49. end;
  50. function IsPendingReboot: Boolean;
  51. var
  52. Value: String;
  53. begin
  54. Result := RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations', Value) or
  55. (RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'SetupExecute', Value) and (Value <> ''));
  56. end;
  57. function InstallProducts: InstallResult;
  58. var
  59. ResultCode, I, ProductCount: Integer;
  60. begin
  61. Result := InstallSuccessful;
  62. ProductCount := GetArrayLength(Dependencies);
  63. MemoInstallInfo := SetupMessage(msgReadyMemoTasks);
  64. if ProductCount > 0 then begin
  65. DownloadPage.Show;
  66. for I := 0 to ProductCount - 1 do begin
  67. if Dependencies[I].InstallClean and (DelayedReboot or IsPendingReboot) then begin
  68. Result := InstallRebootRequired;
  69. break;
  70. end;
  71. DownloadPage.SetText(Dependencies[I].Title, '');
  72. DownloadPage.SetProgress(I + 1, ProductCount);
  73. while True do begin
  74. ResultCode := 0;
  75. if ShellExec('', ExpandConstant('{tmp}{\}') + Dependencies[I].Filename, Dependencies[I].Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then begin
  76. if Dependencies[I].RebootAfter then begin
  77. // delay reboot after install if we installed the last dependency anyways
  78. if I = ProductCount - 1 then begin
  79. DelayedReboot := True;
  80. end else begin
  81. Result := InstallRebootRequired;
  82. MemoInstallInfo := Dependencies[I].Title;
  83. end;
  84. break;
  85. end else if (ResultCode = 0) or Dependencies[I].ForceSuccess then begin
  86. break;
  87. end else if ResultCode = 3010 then begin
  88. // Windows Installer ResultCode 3010: ERROR_SUCCESS_REBOOT_REQUIRED
  89. DelayedReboot := True;
  90. break;
  91. end;
  92. end;
  93. case SuppressibleMsgBox(FmtMessage(SetupMessage(msgErrorFunctionFailed), [Dependencies[I].Title, IntToStr(ResultCode)]), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
  94. IDABORT: begin
  95. Result := InstallError;
  96. MemoInstallInfo := MemoInstallInfo + #13#10 + ' ' + Dependencies[I].Title;
  97. break;
  98. end;
  99. IDIGNORE: begin
  100. MemoInstallInfo := MemoInstallInfo + #13#10 + ' ' + Dependencies[I].Title;
  101. break;
  102. end;
  103. end;
  104. end;
  105. if Result <> InstallSuccessful then begin
  106. break;
  107. end;
  108. end;
  109. DownloadPage.Hide;
  110. end;
  111. end;
  112. // Inno Setup event functions
  113. procedure InitializeWizard;
  114. begin
  115. DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil);
  116. end;
  117. function PrepareToInstall(var NeedsRestart: Boolean): String;
  118. begin
  119. DelayedReboot := False;
  120. case InstallProducts of
  121. InstallError: begin
  122. Result := MemoInstallInfo;
  123. end;
  124. InstallRebootRequired: begin
  125. Result := MemoInstallInfo;
  126. NeedsRestart := True;
  127. // write into the registry that the installer needs to be executed again after restart
  128. RegWriteStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'InstallBootstrap', ExpandConstant('{srcexe}'));
  129. end;
  130. end;
  131. end;
  132. function NeedRestart: Boolean;
  133. begin
  134. Result := DelayedReboot;
  135. end;
  136. function UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
  137. begin
  138. Result := '';
  139. if MemoUserInfoInfo <> '' then begin
  140. Result := Result + MemoUserInfoInfo + Newline + NewLine;
  141. end;
  142. if MemoDirInfo <> '' then begin
  143. Result := Result + MemoDirInfo + Newline + NewLine;
  144. end;
  145. if MemoTypeInfo <> '' then begin
  146. Result := Result + MemoTypeInfo + Newline + NewLine;
  147. end;
  148. if MemoComponentsInfo <> '' then begin
  149. Result := Result + MemoComponentsInfo + Newline + NewLine;
  150. end;
  151. if MemoGroupInfo <> '' then begin
  152. Result := Result + MemoGroupInfo + Newline + NewLine;
  153. end;
  154. if MemoTasksInfo <> '' then begin
  155. Result := Result + MemoTasksInfo;
  156. end;
  157. if MemoInstallInfo <> '' then begin
  158. if MemoTasksInfo = '' then begin
  159. Result := Result + SetupMessage(msgReadyMemoTasks);
  160. end;
  161. Result := Result + FmtMessage(MemoInstallInfo, [Space]);
  162. end;
  163. end;
  164. function NextButtonClick(const CurPageID: Integer): Boolean;
  165. var
  166. I, ProductCount: Integer;
  167. Retry: Boolean;
  168. begin
  169. Result := True;
  170. if (CurPageID = wpReady) and (MemoInstallInfo <> '') then begin
  171. DownloadPage.Show;
  172. ProductCount := GetArrayLength(Dependencies);
  173. for I := 0 to ProductCount - 1 do begin
  174. if Dependencies[I].URL <> '' then begin
  175. DownloadPage.Clear;
  176. DownloadPage.Add(Dependencies[I].URL, Dependencies[I].Filename, Dependencies[I].Checksum);
  177. Retry := True;
  178. while Retry do begin
  179. Retry := False;
  180. try
  181. DownloadPage.Download;
  182. except
  183. if GetExceptionMessage = SetupMessage(msgErrorDownloadAborted) then begin
  184. Result := False;
  185. I := ProductCount;
  186. end else begin
  187. case SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
  188. IDABORT: begin
  189. Result := False;
  190. I := ProductCount;
  191. end;
  192. IDRETRY: begin
  193. Retry := True;
  194. end;
  195. end;
  196. end;
  197. end;
  198. end;
  199. end;
  200. end;
  201. DownloadPage.Hide;
  202. end;
  203. end;
  204. // architecture helper functions
  205. function IsX64: Boolean;
  206. begin
  207. Result := not ForceX86 and Is64BitInstallMode;
  208. end;
  209. function GetString(const x86, x64: String): String;
  210. begin
  211. if IsX64 then begin
  212. Result := x64;
  213. end else begin
  214. Result := x86;
  215. end;
  216. end;
  217. function GetArchitectureSuffix: String;
  218. begin
  219. Result := GetString('', '_x64');
  220. end;
  221. function GetArchitectureTitle: String;
  222. begin
  223. Result := GetString(' (x86)', ' (x64)');
  224. end;
  225. function CompareVersion(const Version1, Version2: String): Integer;
  226. var
  227. Position, Number1, Number2: Integer;
  228. begin
  229. Result := 0;
  230. while (Version1 <> '') or (Version2 <> '') do begin
  231. Position := Pos('.', Version1);
  232. if Position > 0 then begin
  233. Number1 := StrToIntDef(Copy(Version1, 1, Position - 1), 0);
  234. Delete(Version1, 1, Position);
  235. end else if Version1 <> '' then begin
  236. Number1 := StrToIntDef(Version1, 0);
  237. Version1 := '';
  238. end else begin
  239. Number1 := 0;
  240. end;
  241. Position := Pos('.', Version2);
  242. if Position > 0 then begin
  243. Number2 := StrToIntDef(Copy(Version2, 1, Position - 1), 0);
  244. Delete(Version2, 1, Position);
  245. end else if Version2 <> '' then begin
  246. Number2 := StrToIntDef(Version2, 0);
  247. Version2 := '';
  248. end else begin
  249. Number2 := 0;
  250. end;
  251. if Number1 < Number2 then begin
  252. Result := -1;
  253. break;
  254. end else if Number1 > Number2 then begin
  255. Result := 1;
  256. break;
  257. end;
  258. end;
  259. end;
  260. { Check if dotnet is installed }
  261. function IsAspDotNetInstalled: Boolean;
  262. var
  263. ResultCode: Integer;
  264. begin
  265. Result := false;
  266. Exec('cmd.exe', '/c dotnet --list-runtimes | find /n "Microsoft.AspNetCore.App 8.0.6"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  267. if ResultCode = 0 then
  268. begin
  269. Result := true;
  270. end;
  271. end;
  272. function IsDotNetDesktopInstalled: Boolean;
  273. var
  274. ResultCode: Integer;
  275. begin
  276. Result := false;
  277. Exec('cmd.exe', '/c dotnet --list-runtimes | find /n "Microsoft.WindowsDesktop.App 8.0.6"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
  278. if ResultCode = 0 then
  279. begin
  280. Result := true;
  281. end;
  282. end;
  283. { if dotnet is not installed then add it for download }
  284. procedure CheckDotnetDependency;
  285. begin
  286. if not IsAspDotNetInstalled then
  287. begin
  288. AddDependency('aspdotnet80' + GetArchitectureSuffix + '.exe',
  289. '/lcid ' + IntToStr(GetUILanguage) + ' /passive /norestart',
  290. 'ASP.NET Core Runtime 8.0.6' + GetArchitectureTitle,
  291. GetString('https://download.visualstudio.microsoft.com/download/pr/88a7d3f3-615e-4771-8709-1e16873645b3/a36f311385df553e54201137f53d041e/aspnetcore-runtime-8.0.6-win-x86.exe', 'https://download.visualstudio.microsoft.com/download/pr/38b32fc8-8070-4f14-bd52-65505fddc5ff/50e6cf3b7505eee02c3b3db8ea46ffe3/aspnetcore-runtime-8.0.6-win-x64.exe'),
  292. '', False, False, False);
  293. end;
  294. if not IsDotNetDesktopInstalled then
  295. begin
  296. AddDependency('dotnet80desktop' + GetArchitectureSuffix + '.exe',
  297. '/lcid ' + IntToStr(GetUILanguage) + ' /passive /norestart',
  298. '.NET Desktop Runtime 8.0.6' + GetArchitectureTitle,
  299. GetString('https://download.visualstudio.microsoft.com/download/pr/fb4a2e70-0c24-42f8-a549-4ea2b6e16831/e7bf08360f9c96ad3a90b0eb2edf96c0/windowsdesktop-runtime-8.0.6-win-x86.exe', 'https://download.visualstudio.microsoft.com/download/pr/76e5dbb2-6ae3-4629-9a84-527f8feb709c/09002599b32d5d01dc3aa5dcdffcc984/windowsdesktop-runtime-8.0.6-win-x64.exe'),
  300. '', False, False, False);
  301. end;
  302. end;