Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. {*
  2. * This application launches the dmdirc java-based installer.
  3. *
  4. * DMDirc - Open Source IRC Client
  5. * Copyright (c) 2006-2008 Chris Smith, Shane Mc Cormack, Gregory Holmes
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. *}
  25. program Setup;
  26. {$R most.res}
  27. {$IFDEF FPC}
  28. {$MODE Delphi}
  29. {$ENDIF}
  30. // Use this instead of {$APPTYPE XXX}
  31. // APP_XXX is the same as {$APPTYPE XXX}
  32. // Defaults to console
  33. // This is a work-around for a bug in FPC Cross Compiling to windows in delphi
  34. // mode (IsConsole is always true)
  35. {$DEFINE APP_GUI}
  36. // This block actually does the work for the above work-around
  37. {$IFDEF APP_GUI}
  38. {$APPTYPE GUI}
  39. {$ELSE}
  40. {$IFDEF APP_FS}
  41. {$APPTYPE FS}
  42. {$ELSE}
  43. {$IFDEF APP_TOOL}
  44. {$DEFINE APP_CONSOLE}
  45. {$APPTYPE TOOL}
  46. {$ELSE}
  47. {$DEFINE APP_CONSOLE}
  48. {$APPTYPE CONSOLE}
  49. {$ENDIF}
  50. {$ENDIF}
  51. {$ENDIF}
  52. // If this is defined, lazarus-specific code (gui progress bar) will be compiled
  53. // without it, a wget console window will be used for progress instead.
  54. // This is automatically set by the build script when lazarus is detected in /usr/lib/lazarus
  55. // You can forcibly define or undefine it here.
  56. // {$DEFINE LAZARUS}
  57. // {$UNDEF LAZARUS}
  58. uses
  59. {$IFDEF LAZARUS}Interfaces, Forms, ComCtrls, Buttons, Messages, Controls, StdCtrls, {$ENDIF}
  60. Vista, Windows, SysUtils, classes, registry, strutils {$IFNDEF FPC},masks{$ENDIF};
  61. {$IFDEF LAZARUS}
  62. type
  63. TProgressForm = class(TForm)
  64. ProgressBar: TProgressBar;
  65. CancelButton: TButton;
  66. CaptionLabel: TLabel;
  67. constructor Create(AOwner: TComponent); override;
  68. private
  69. procedure onButtonClick(Sender: TObject);
  70. public
  71. procedure setProgress(value: integer);
  72. end;
  73. {$ENDIF}
  74. const
  75. {$I SetupConsts.inc}
  76. // This is also part of the above work-around.
  77. {$IFDEF APP_CONSOLE}
  78. IsConsole: boolean = true;
  79. {$ELSE}
  80. IsConsole: boolean = false;
  81. {$ENDIF}
  82. var
  83. {$IFDEF LAZARUS} form: TProgressForm; {$ENDIF}
  84. terminateDownload: boolean = false;
  85. {$IFDEF LAZARUS}
  86. constructor TProgressForm.Create(AOwner: TComponent);
  87. begin
  88. inherited;
  89. self.Width := 500;
  90. self.Height := 80;
  91. self.Position := poScreenCenter;
  92. self.BorderStyle := bsSingle;
  93. CaptionLabel := TLabel.create(self);
  94. CaptionLabel.Parent := self;
  95. CaptionLabel.Width := 490;
  96. CaptionLabel.Height := 15;
  97. CaptionLabel.Top := 5;
  98. CaptionLabel.Left := 5;
  99. CaptionLabel.Caption := 'Downloading JRE - 0%';
  100. ProgressBar := TProgressBar.create(self);
  101. ProgressBar.Parent := self;
  102. ProgressBar.Width := 490;
  103. ProgressBar.Height := 20;
  104. ProgressBar.Top := CaptionLabel.Top+CaptionLabel.Height+5;
  105. ProgressBar.Left := 5;
  106. ProgressBar.Visible := true;
  107. ProgressBar.Max := 100;
  108. ProgressBar.Position := 0;
  109. CancelButton := TButton.create(self);
  110. CancelButton.Parent := self;
  111. CancelButton.Width := 80;
  112. CancelButton.Height := 25;
  113. CancelButton.Top := ProgressBar.Top+ProgressBar.Height+5;
  114. CancelButton.Left := Round((self.Width/2) - (CancelButton.Width/2));
  115. CancelButton.Visible := true;
  116. CancelButton.Caption := 'Cancel';
  117. CancelButton.onClick := self.onButtonClick;
  118. self.Caption := pChar('DMDirc Setup');
  119. Application.Title := self.Caption;
  120. SetVistaFonts(self);
  121. end;
  122. procedure TProgressForm.onButtonClick(Sender: TObject);
  123. begin
  124. terminateDownload := true;
  125. end;
  126. procedure TProgressForm.setProgress(value: integer);
  127. begin
  128. ProgressBar.Position := value;
  129. CaptionLabel.Caption := pchar('Downloading JRE - '+inttostr(value)+'%');
  130. self.Caption := pChar('DMDirc Setup - '+CaptionLabel.Caption);
  131. Application.Title := self.Caption;
  132. end;
  133. {$ENDIF}
  134. function askQuestion(Question: String): boolean;
  135. begin
  136. Result := TaskDialog(0, 'DMDirc Setup', 'Question', Question, TD_ICON_QUESTION, TD_BUTTON_YES + TD_BUTTON_NO) = mrYes;
  137. end;
  138. procedure showError(ErrorMessage: String; addFooter: boolean = true; includeDescInXP: boolean = true);
  139. begin
  140. if IsConsole then begin
  141. writeln('');
  142. writeln('-----------------------------------------------------------------------');
  143. writeln('Sorry, setup is unable to continue.!');
  144. writeln('-----------------------------------------------------------------------');
  145. writeln('Reason:');
  146. writeln('----------');
  147. writeln(ErrorMessage);
  148. if addFooter then begin
  149. writeln('-----------------------------------------------------------------------');
  150. writeln('If you feel this is incorrect, or you require some further assistance,');
  151. writeln('please feel free to contact us.');
  152. end;
  153. writeln('-----------------------------------------------------------------------');
  154. readln;
  155. end
  156. else begin
  157. if addFooter then begin
  158. ErrorMessage := ErrorMessage+#13#10;
  159. ErrorMessage := ErrorMessage+#13#10+'If you feel this is incorrect, or you require some further assistance,';
  160. if not IsWindowsVista then ErrorMessage := ErrorMessage+#13#10;
  161. ErrorMessage := ErrorMessage+'please feel free to contact us.';
  162. end;
  163. TaskDialog(0, 'DMDirc Setup', 'Sorry, setup is unable to continue.', ErrorMessage, TD_ICON_ERROR, TD_BUTTON_OK, includeDescInXP, false);
  164. end;
  165. end;
  166. procedure showmessage(message: String; context:String = 'Information');
  167. begin
  168. if IsConsole then begin
  169. writeln('');
  170. writeln('-----------------------------------------------------------------------');
  171. writeln(context+':');
  172. writeln('-----------------------------------------------------------------------');
  173. writeln(message);
  174. writeln('-----------------------------------------------------------------------');
  175. readln;
  176. end
  177. else begin
  178. TaskDialog(0, 'DMDirc Setup', context, message, TD_ICON_INFORMATION, TD_BUTTON_OK);
  179. end;
  180. end;
  181. // Run an application and don't wait for it to finish.
  182. function Launch(sProgramToRun: String; hide: boolean = false): TProcessInformation;
  183. var
  184. StartupInfo: TStartupInfo;
  185. begin
  186. FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  187. with StartupInfo do begin
  188. cb := SizeOf(TStartupInfo);
  189. dwFlags := STARTF_USESHOWWINDOW;
  190. if hide then wShowWindow := SW_HIDE
  191. else wShowWindow := SW_SHOWNORMAL;
  192. end;
  193. CreateProcess(nil, PChar(sProgramToRun), nil, nil, False, NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, Result);
  194. end;
  195. // Run an application and wait for it to finish.
  196. function ExecAndWait(sProgramToRun: String; hide: boolean = false): Longword;
  197. var
  198. ProcessInfo: TProcessInformation;
  199. begin
  200. ProcessInfo := Launch(sProgramToRun, hide);
  201. getExitCodeProcess(ProcessInfo.hProcess, Result);
  202. while Result=STILL_ACTIVE do begin
  203. sleep(1000);
  204. GetExitCodeProcess(ProcessInfo.hProcess, Result);
  205. end;
  206. end;
  207. procedure dowriteln(line: String);
  208. begin
  209. if IsConsole then writeln(line);
  210. end;
  211. procedure dowrite(line: String);
  212. begin
  213. if IsConsole then write(line);
  214. end;
  215. function GetFileSizeByName(name: String): Integer;
  216. var
  217. hand: THandle;
  218. begin
  219. hand := 0;
  220. Result := 0;
  221. if FileExists(name) then begin
  222. try
  223. hand := CreateFile(PChar(name), GENERIC_READ, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  224. Result := GetFileSize(hand, nil);
  225. finally
  226. try
  227. if (hand <> 0) then CloseHandle(hand);
  228. except
  229. Result := -1;
  230. end;
  231. end;
  232. end;
  233. end;
  234. function DoMatch(Input: String; Wildcard: String): boolean;
  235. begin
  236. {$ifdef FPC}
  237. Result := IsWild(Input,Wildcard,True);
  238. {$else}
  239. Result := MatchesMask(Input,Wildcard);
  240. {$endif}
  241. end;
  242. {$IFNDEF VER150}
  243. function AnsiMidStr(Source: String; Start: Integer; Count: Integer): String;
  244. begin
  245. // Not perfectly accurate, but does the job
  246. Result := Copy(Source, Start, Count);
  247. end;
  248. {$ENDIF}
  249. function downloadJRE(message: String = 'Would you like to download the java JRE?'): boolean;
  250. var
  251. ProcessInfo: TProcessInformation;
  252. processResult: Longword;
  253. url: String;
  254. dir: String;
  255. line: String;
  256. f: TextFile;
  257. bits: TStringList;
  258. match: boolean;
  259. {$IFDEF LAZARUS}
  260. wantedsize: double;
  261. currentsize: double;
  262. {$ENDIF}
  263. begin
  264. dir := IncludeTrailingPathDelimiter(ExtractFileDir(paramstr(0)));
  265. url := 'http://www.dmdirc.com/getjava/windows/all';
  266. Result := false;
  267. ExecAndWait('wget.exe -o '+dir+'wgetoutput --spider '+url, true);
  268. AssignFile(f, dir+'wgetoutput');
  269. Reset(f);
  270. line := '';
  271. match := false;
  272. while not Eof(f) do begin
  273. ReadLn(f, line);
  274. match := DoMatch(line,'Length:*');
  275. if match then break;
  276. end;
  277. if match then begin
  278. bits := TStringList.create;
  279. try
  280. bits.Clear;
  281. bits.Delimiter := ' ';
  282. bits.DelimitedText := line;
  283. {$IFDEF LAZARUS}
  284. try
  285. wantedsize := strtoint(StringReplace(bits[1], ',', '', [rfReplaceAll]))
  286. except
  287. wantedsize := 0;
  288. end;
  289. {$ENDIF}
  290. if askQuestion(message+' (Download Size: '+AnsiMidStr(bits[2], 2, length(bits[2])-2)+')') then begin
  291. {$IFDEF LAZARUS}
  292. ProcessInfo := Launch('wget.exe '+url+' -O jre.exe', true);
  293. form.show();
  294. if wantedsize <= 0 then begin
  295. form.setProgress(50);
  296. end;
  297. {$ELSE}
  298. ProcessInfo := Launch('wget.exe '+url+' -O jre.exe');
  299. {$ENDIF}
  300. getExitCodeProcess(ProcessInfo.hProcess, processResult);
  301. while (processResult=STILL_ACTIVE) and (not terminateDownload) do begin
  302. // Update progress bar.
  303. {$IFDEF LAZARUS}
  304. if wantedsize > 0 then begin
  305. currentsize := GetFileSizeByName('jre.exe');
  306. if (currentsize > 0) then form.setProgress(Round((currentsize/wantedsize)*100));
  307. end;
  308. Application.ProcessMessages;
  309. {$ENDIF}
  310. sleep(10);
  311. GetExitCodeProcess(ProcessInfo.hProcess, processResult);
  312. end;
  313. {$IFDEF LAZARUS}form.hide();{$ENDIF}
  314. if (terminateDownload) then begin
  315. Result := false;
  316. {$IFDEF LAZARUS}
  317. TerminateProcess(ProcessInfo.hProcess, 0);
  318. showError('JRE Download was aborted', false);
  319. {$ENDIF}
  320. end
  321. else Result := processResult = 0;
  322. if not Result then begin
  323. if not terminateDownload then begin
  324. showError('JRE Download Failed', false);
  325. end
  326. else begin
  327. // If the download was cancelled by the form, this error will already
  328. // have been given.
  329. {$IFNDEF LAZARUS}
  330. showError('JRE Download was aborted', false);
  331. {$ENDIF}
  332. end;
  333. end;
  334. end;
  335. finally
  336. bits.free;
  337. end;
  338. end;
  339. end;
  340. function installJRE(isUpgrade: boolean): boolean;
  341. var
  342. question: String;
  343. needDownload: boolean;
  344. canContinue: boolean;
  345. begin
  346. Result := false;
  347. needDownload := not FileExists(IncludeTrailingPathDelimiter(ExtractFileDir(paramstr(0)))+'jre.exe');
  348. if needDownload then begin
  349. if not isUpgrade then question := 'Java was not detected on your machine. Would you like to download and install it now?'
  350. else question := 'The version of java detected on your machine is not compatible with DMDirc. Would you like to download and install a compatible version now?';
  351. end
  352. else begin
  353. if not isUpgrade then question := 'Java was not detected on your machine. Would you like to install it now?'
  354. else question := 'The version of java detected on your machine is not compatible with DMDirc. Would you like to install a compatible version now?';
  355. end;
  356. canContinue := true;
  357. if (needDownload) then begin
  358. canContinue := downloadJRE(question);
  359. end;
  360. if canContinue then begin
  361. // Final result of this function is the return value of installing java.
  362. if needDownload or askQuestion(question) then begin
  363. showmessage('The Java installer will now run. Please follow the instructions given. '+#13#10+'The DMDirc installation will continue afterwards.');
  364. Result := (ExecAndWait('jre.exe') = 0);
  365. end;
  366. end
  367. end;
  368. var
  369. errorMessage: String;
  370. javaCommand: String = 'javaw.exe';
  371. params: String = '';
  372. dir: String = '';
  373. Reg: TRegistry;
  374. result: Integer;
  375. begin
  376. {$IFDEF LAZARUS}
  377. Application.Initialize;
  378. Application.CreateForm(TProgressForm, form);
  379. {$ENDIF}
  380. if IsConsole then begin
  381. writeln('-----------------------------------------------------------------------');
  382. writeln('Welcome to the DMDirc installer.');
  383. writeln('-----------------------------------------------------------------------');
  384. writeln('This will install DMDirc on your computer.');
  385. writeln('');
  386. writeln('Please wait whilst the GUI part of the installer loads...');
  387. writeln('-----------------------------------------------------------------------');
  388. // end
  389. // else begin
  390. // errorMessage := 'This will install DMDirc on your computer, please click OK to continue, or Cancel to abort.';
  391. // if (MessageBox(0, PChar(errorMessage), 'DMDirc Installer', MB_OKCANCEL + MB_ICONINFORMATION) <> IDOK) then begin
  392. // exit;
  393. // end;
  394. end;
  395. errorMessage := '';
  396. dowrite('Checking for DMDirc.jar.. ');
  397. if FileExists('DMDirc.jar') then begin
  398. dowriteln('Success!');
  399. dowrite('Checking for JVM.. ');
  400. if (ExecAndWait(javaCommand+' -version') <> 0) then begin
  401. dowriteln('Failed!');
  402. if not installJRE(false) then begin
  403. showError('DMDirc setup can not continue without java. Please install java and try again', false, false);
  404. exit;
  405. end;
  406. end
  407. else begin
  408. if IsConsole then begin
  409. writeln('Success!');
  410. write('Starting installer.. ');
  411. javaCommand := 'java.exe';
  412. end;
  413. end;
  414. Reg := TRegistry.Create;
  415. Reg.RootKey := HKEY_LOCAL_MACHINE;
  416. if Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DMDirc', false) then begin
  417. dir := Reg.ReadString('InstallDir');
  418. if (dir <> '') then begin
  419. params := params+' --directory "'+dir+'"';
  420. end;
  421. end;
  422. Reg.CloseKey;
  423. Reg.Free;
  424. if (ReleaseNumber <> '') then begin
  425. params := params+' --release '+ReleaseNumber;
  426. end;
  427. // Check if the installer runs
  428. if (ExecAndWait(javaCommand+' -cp DMDirc.jar com.dmdirc.installer.Main --help') <> 0) then begin
  429. dowriteln('Failed!');
  430. if not installJRE(true) then begin
  431. showError('Sorry, DMDirc setup can not continue without an updated version of java.', false, false);
  432. exit;
  433. end
  434. else begin
  435. // Try again now that java is installed.
  436. result := ExecAndWait(javaCommand+' -cp DMDirc.jar com.dmdirc.installer.Main '+params);
  437. end;
  438. end
  439. else begin
  440. // Java is the right version, run the installer
  441. result := ExecAndWait(javaCommand+' -cp DMDirc.jar com.dmdirc.installer.Main '+params);
  442. end;
  443. if result = 0 then dowriteln('Installation completed.')
  444. else dowriteln('Installation did not complete.')
  445. end
  446. else begin
  447. dowriteln('Failed!');
  448. errorMessage := errorMessage+'DMDirc.jar was not found.';
  449. errorMessage := errorMessage+#13#10;
  450. errorMessage := errorMessage+#13#10+'This is likely because of a corrupt installer build.';
  451. errorMessage := errorMessage+#13#10+'Please check http://www.dmdirc.com/ for an updated build.';
  452. showError(errorMessage);
  453. end;
  454. if IsConsole then begin
  455. writeln('');
  456. writeln('-----------------------------------------------------------------------');
  457. writeln('Installation Completed. Thank you for choosing DMDirc');
  458. writeln('-----------------------------------------------------------------------');
  459. end;
  460. end.