Win32 Application Online Update (Automatically)

As my promise before, here now I present the last part of updating Win32 application methods. On this experiment, I tried to implement an automatically technique so that it will eliminate user’s response to retrieve an upgrade from online source. Any programming language will do the same technique I offered but for this chance, still I used Borland Delphi for the familiarly reason. The trick – I said – is a basic one: first, the form needs to download a text file containing application version number information from the web, meanwhile at the same time the form also need to load the current application version. Then, both numbers must be compared. If newer version detected, the form have to download the update package. That’s it simple.

To get start, create a blank project and fill the form with 2 TMemo’s (to store both version local & online), TStatusBar (to show information during update process), TProgressBar (to show percentage progress), TTimer (to automatically do the process) and a TButton for dummy button test.



Next, please provide a text file (containing latest version number) and an exe package which is latest application to download into an online web directory (for example: http://www.abc.com/download). For this experiment, I used data.txt and data.exe.



Back to Delphi’s editor and think for the first rule of the form; download data.txt from http://www.abc.com/download/data.txt to the disk of local PC. The question is, is it possible to download an Internet file without using a special "download" component? Fortunately, since Delphi 4, this can be done very easily by using the Windows API function URLDownloadToFile. But, it's a pity that this function is not documented in the Help of the earlier Delphi versions, except in Delphi 2006 and later which is mentioned in the Help documents.

To do the trick, firstly, add "URLMon" to the unit's USES clause, if it's not already in the USES clause:

Uses Windows, Messages, …, URLMon;


Then, use the following simple source code example:

if URLDownloadToFile(nil, PChar(SourceFile), PChar(LocalFile), 0, nil) = 0 then CHECK LATEST VERSION & DOWNLOAD IT IF POSSIBLE
else StatusBar1.Panels[0].Text:='Error downloading';

CHECK LATEST VERSION means that both version number (from local & online) need to be compared. If it detected a latest one, make data.exe download directly. For the download progress - in a real world "critical" application - you should give some feedback to the user about what's happening, such as: disable the button until the end of the download, show progress indicator or show some message in a status bar. If you need to save the contents of http://www.abc.com/download/data.exe - and be able to track the download progress, use the TDownLoadURL Delphi action. While TDownLoadURL is writing to the specified file, it periodically generates an OnDownloadProgress event, so that you can provide users with feedback about the process. For this purpose, add unit “ExtActns” in the uses clause.

Uses Windows, Messages, …, URLMon, ExtActns;

type
TForm1 = class(TForm)

private
{ Private declarations }
procedure URL_OnDownloadProgress
(Sender: TDownLoadURL;
Progress, ProgressMax: Cardinal;
StatusCode: TURLDownloadStatus;
StatusText: String; var Cancel: Boolean) ;

implementation

procedure TForm1.URL_OnDownloadProgress;
begin
ProgressBar1.Max:= ProgressMax;
ProgressBar1.Position:= Progress;
end;


procedure TForm1.Button1Click(Sender: TObject);
with TDownloadURL.Create(self) do
try
URL:= http://www.abc.com/download/'data.exe';
FileName := 'e:\data.exe';
OnDownloadProgress := URL_OnDownloadProgress;
ExecuteTarget(nil) ;
finally
Free;
end;
end;
end;


Ok then, note that rule #2 using button as dummy trigger to download the whole process – from data.txt until data.exe -, so that Button1Click event complete like the following source:

procedure TForm1.Button1Click(Sender: TObject);
var wwwString,SourceFile, LocalFile: string;
begin
// initialization
Button1.Enabled:=false;
Memo1.Clear;
Memo2.Clear;
try
Memo1.Lines.LoadFromFile('c:\data.txt');
except
// if it failed to load data.txt from C:
end;
wwwString:='http://www.abc.com/download/'; // online source
SourceFile := wwwString+'data.txt';
LocalFile := 'c:\data.tmp.txt'; // temporary for data.txt

// try to download data.txt from online source
if URLDownloadToFile(nil, PChar(SourceFile), PChar(LocalFile), 0, nil) = 0 then
begin
Memo2.Lines.LoadFromFile('c:\data.tmp.txt');
// compare both version number (local & online)
if Memo1.Text>=Memo2.Text then StatusBar1.Panels[0].Text:='No update available'
else
begin
Memo2.Lines.SaveToFile('e:\data.txt'); // save latest version information
StatusBar1.Panels[0].Text:='Downloading update ('+Memo2.Text+')...';
// downloading latest application
with TDownloadURL.Create(self) do
try
URL:=wwwString+'data.exe';
FileName := 'c:\data.exe';
OnDownloadProgress := URL_OnDownloadProgress;
ExecuteTarget(nil) ;
finally
Free;
end;
end;
end
else
StatusBar1.Panels[0].Text:='Error downloading ' + SourceFile;
deletefile('c:\data.tmp.txt'); // delete temporary
Button1.Enabled:=true;
end;


Make a try to execute the source & press the button to start the (manual) update.



If nothing goes wrong, for the first time, the application will try to start download the latest application. Wait it until the rest process completed. If it succeeded, you may need to move the download trigger into TTimer. And that’s it, the updater application will work. You can add some improvement to the updater such as a procedure to move data.exe into main program or anything you like after you built the updater like above. Please share your comment below & thanks for your attention on this blog.

Labels: , ,


PS: If you've benefit from this blog,
you can support it by making a small contribution.

Enter your email address to receive feed update from this blog:

Post a Comment

 

Post a Comment

Leave comments here...