mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Updatecheck: Find a batchfile-solution to replace the running exe with a downloaded build.
TODO: find some sleep command for the batch file, as we sometimes get "access denied" while trying to overwrite the just terminated exe. Seems like taskkill doesn't close all handles itself.
This commit is contained in:
@ -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}
|
||||
|
||||
|
@ -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}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{53d02113-9bb2-4326-83eb-53734f07dae7}</ProjectGuid>
|
||||
<MainSource>heidisql.dpr</MainSource>
|
||||
@ -137,6 +137,9 @@
|
||||
<DCCReference Include="..\..\source\updatecheck.pas">
|
||||
<Form>frmUpdateCheck</Form>
|
||||
</DCCReference>
|
||||
<DCCReference Include="..\..\source\updatedownload.pas">
|
||||
<Form>frmUpdateDownload</Form>
|
||||
</DCCReference>
|
||||
<DCCReference Include="..\..\source\usermanager.pas">
|
||||
<Form>UserManagerForm</Form>
|
||||
</DCCReference>
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
51
source/updatedownload.dfm
Normal file
51
source/updatedownload.dfm
Normal file
@ -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
|
130
source/updatedownload.pas
Normal file
130
source/updatedownload.pas
Normal file
@ -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.
|
Reference in New Issue
Block a user