diff --git a/packages/delphi10/heidisql.dpr b/packages/delphi10/heidisql.dpr index c43edcfc..e6888f04 100644 --- a/packages/delphi10/heidisql.dpr +++ b/packages/delphi10/heidisql.dpr @@ -35,7 +35,8 @@ uses data_sorting in '..\..\source\data_sorting.pas' {DataSortingForm}, runsqlfile in '..\..\source\runsqlfile.pas' {RunSQLFileForm}, createdatabase in '..\..\source\createdatabase.pas' {CreateDatabaseForm}, - updatecheck in '..\..\source\updatecheck.pas' {frmUpdateCheck}; + updatecheck in '..\..\source\updatecheck.pas' {frmUpdateCheck}, + updatedownload in '..\..\source\updatedownload.pas' {frmUpdateDownload}; {$R *.RES} diff --git a/packages/delphi11/heidisql.dpr b/packages/delphi11/heidisql.dpr index c43edcfc..e6888f04 100644 --- a/packages/delphi11/heidisql.dpr +++ b/packages/delphi11/heidisql.dpr @@ -35,7 +35,8 @@ uses data_sorting in '..\..\source\data_sorting.pas' {DataSortingForm}, runsqlfile in '..\..\source\runsqlfile.pas' {RunSQLFileForm}, createdatabase in '..\..\source\createdatabase.pas' {CreateDatabaseForm}, - updatecheck in '..\..\source\updatecheck.pas' {frmUpdateCheck}; + updatecheck in '..\..\source\updatecheck.pas' {frmUpdateCheck}, + updatedownload in '..\..\source\updatedownload.pas' {frmUpdateDownload}; {$R *.RES} diff --git a/packages/delphi11/heidisql.dproj b/packages/delphi11/heidisql.dproj index d3e6d971..4882c475 100644 --- a/packages/delphi11/heidisql.dproj +++ b/packages/delphi11/heidisql.dproj @@ -1,4 +1,4 @@ - + {53d02113-9bb2-4326-83eb-53734f07dae7} heidisql.dpr @@ -137,6 +137,9 @@
frmUpdateCheck
+ +
frmUpdateDownload
+
UserManagerForm
diff --git a/source/helpers.pas b/source/helpers.pas index 21be5312..b6f2761a 100644 --- a/source/helpers.pas +++ b/source/helpers.pas @@ -85,6 +85,7 @@ type function TColorToHex( Color : TColor ): string; function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0 ): TStringList; function Pos2(const Needle, HayStack: string; const StartPos: Integer) : Integer; + function GetTempDir: String; procedure ExtractUpdater; procedure UpdateItWith(const _file: String); @@ -2138,6 +2139,15 @@ begin end; +function GetTempDir: String; +var + TempPath: array[0..MAX_PATH] of Char; +begin + GetTempPath(MAX_PATH, @TempPath); + Result := StrPas(TempPath); +end; + + {** Extract the updater from resource. diff --git a/source/updatecheck.pas b/source/updatecheck.pas index 92046cd7..997f903c 100644 --- a/source/updatecheck.pas +++ b/source/updatecheck.pas @@ -34,7 +34,7 @@ type implementation -uses helpers, main; +uses helpers, main, UpdateDownload; {$R *.dfm} @@ -65,7 +65,6 @@ end; } procedure TfrmUpdateCheck.FormShow(Sender: TObject); var - TempPath: array[0..MAX_PATH] of Char; reg : TRegistry; begin Status('Initiating ... '); @@ -78,13 +77,10 @@ begin memoRelease.Clear; memoBuild.Clear; - // Detect temp directory - GetTempPath(MAX_PATH, @TempPath); - // Prepare download CheckfileDownload := TDownLoadURL.Create(Self); CheckfileDownload.URL := APPDOMAIN + 'updatecheck.php'; - CheckfileDownload.Filename := StrPas(TempPath) + APPNAME + '_updatecheck.ini'; + CheckfileDownload.Filename := GetTempDir + APPNAME + '_updatecheck.ini'; // Download the check file Screen.Cursor := crHourglass; @@ -172,7 +168,7 @@ begin Note := Ini.ReadString(INISECT_BUILD, 'Note', ''); if Note <> '' then memoBuild.Lines.Add( 'Note: ' + Note ); - btnBuild.Caption := 'Download build ' + IntToStr(BuildRevision); + btnBuild.Caption := 'Download and install build ' + IntToStr(BuildRevision); // A new release should have priority over a new nightly build. // So the user should not be able to download a newer build here // before having installed the new release. @@ -197,16 +193,11 @@ end; {** - Download latest build via web browser - TODO: internally replace heidisql.exe: - 1. create a batch file which replaces heidisql.exe - 2. quit Heidi - 3. start the batch - 4. start Heidi + Download latest build and replace running exe } procedure TfrmUpdateCheck.btnBuildClick(Sender: TObject); begin - ShellExec(BuildURL); + DoUpdateDownload(Self, BuildURL, Application.ExeName); end; end. diff --git a/source/updatedownload.dfm b/source/updatedownload.dfm new file mode 100644 index 00000000..1c58e679 --- /dev/null +++ b/source/updatedownload.dfm @@ -0,0 +1,51 @@ +object frmUpdateDownload: TfrmUpdateDownload + Left = 0 + Top = 0 + BorderStyle = bsDialog + Caption = 'Downloading update file ...' + ClientHeight = 95 + ClientWidth = 286 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poOwnerFormCenter + DesignSize = ( + 286 + 95) + PixelsPerInch = 96 + TextHeight = 13 + object lblStatus: TLabel + Left = 8 + Top = 31 + Width = 270 + Height = 28 + Anchors = [akLeft, akTop, akRight] + AutoSize = False + Caption = 'lblStatus' + WordWrap = True + end + object progressDownload: TProgressBar + Left = 8 + Top = 8 + Width = 270 + Height = 17 + Anchors = [akLeft, akTop, akRight] + TabOrder = 0 + end + object btnCancel: TButton + Left = 104 + Top = 62 + Width = 68 + Height = 25 + Anchors = [akLeft, akTop, akRight] + Cancel = True + Caption = 'Cancel' + ModalResult = 2 + TabOrder = 1 + OnClick = btnCancelClick + end +end diff --git a/source/updatedownload.pas b/source/updatedownload.pas new file mode 100644 index 00000000..1cfff8d9 --- /dev/null +++ b/source/updatedownload.pas @@ -0,0 +1,130 @@ +unit updatedownload; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, StdCtrls, ComCtrls, ExtActns, Helpers; + +type + TfrmUpdateDownload = class(TForm) + progressDownload: TProgressBar; + lblStatus: TLabel; + btnCancel: TButton; + procedure btnCancelClick(Sender: TObject); + private + { Private declarations } + Download: TDownLoadURL; + DoCancel: Boolean; + FilePath: String; + procedure DoDownload; + procedure URLOnDownloadProgress(Sender: TDownLoadURL; Progress, ProgressMax: Cardinal; + StatusCode: TURLDownloadStatus; StatusText: String; var Cancel: Boolean); + public + { Public declarations } + end; + +function DoUpdateDownload(AOwner: TComponent; URL, FilePath: String): Boolean; + +implementation + +{$R *.dfm} + + +{** + Initiate the download + update process +} +function DoUpdateDownload(AOwner: TComponent; URL, FilePath: String): Boolean; +var + frm: TfrmUpdateDownload; +begin + Result := False; + frm := TfrmUpdateDownload.Create(AOwner); + frm.Download := TDownLoadURL.Create(frm); + frm.Download.URL := URL; + frm.FilePath := FilePath; + frm.DoDownload; +end; + + +{** + Cancel clicked +} +procedure TfrmUpdateDownload.btnCancelClick(Sender: TObject); +begin + DoCancel := True; +end; + + +{** + Start the download + update process +} +procedure TfrmUpdateDownload.DoDownload; +var + BatchFile: Textfile; + BatchFilename, ExeName: String; +begin + Show; + + // Save the file in a temp directory + Download.Filename := GetTempDir + ExtractFileName(Filepath); + Download.OnDownloadProgress := URLOnDownloadProgress; + + // Delete probably previously downloaded file + if FileExists(Download.Filename) then + DeleteFile(Download.Filename); + + // Do the download + Download.ExecuteTarget(nil); + + // Check if downloaded file exists + if not FileExists(Download.Filename) then begin + Raise Exception.Create('Downloaded file not found: '+Download.Filename); + end; + + if FilePath = Application.ExeName then begin + ExeName := ExtractFilename(FilePath); + BatchFilename := ExtractFilepath(Application.ExeName) + 'Update_' + ExeName + '.cmd'; + AssignFile(BatchFile, BatchFilename); + Rewrite(BatchFile); + WriteLn(BatchFile, 'rem Killing task '+ExeName); + WriteLn(BatchFile, 'taskkill /im "'+ExeName+'" /f'); + // TODO: find some sleep command, as we sometimes get "access denied" + // while trying to overwrite the just terminated exe. Seems like taskkill + // doesn't close all handles itself + WriteLn(BatchFile, 'rem Moving downloaded file to '+ExtractFilepath(FilePath)); + WriteLn(BatchFile, 'move /Y "'+Download.Filename+'" "'+FilePath+'"'); + WriteLn(BatchFile, 'rem Restarting '+APPNAME); + WriteLn(BatchFile, 'start /D"'+ExtractFilepath(FilePath)+'" '+ExeName); + WriteLn(Batchfile); + CloseFile(BatchFile); + // Calling the batchfile will now terminate the running exe... + WinExec(PAnsiChar(BatchFilename), 1); + end else begin + // We're not replacing the running exe, so just move file to destination + MoveFile(PChar(Download.Filename), PChar(FilePath)); + end; + + // Close form + ModalResult := mrOK; +end; + + +{** + Download progress event +} +procedure TfrmUpdateDownload.URLOnDownloadProgress(Sender: TDownLoadURL; Progress, ProgressMax: Cardinal; + StatusCode: TURLDownloadStatus; StatusText: String; var Cancel: Boolean); +begin + progressDownload.Max := ProgressMax; + progressDownload.Position := Progress; + lblStatus.Caption := StatusText; + // Notification if cancel button was pressed + Cancel := DoCancel; + Application.ProcessMessages; +end; + + + + +end.