Software automatic update check
[Mental Studio] Raptor [blog]
Still in "PIA-MyPhotogallery", in order to make the user know the update version of the software in time, I increased the automatic update check. In view of this function, it has a good practical value, so the implementation of this feature is written.
To implement an update check, you need to solve two aspects of questions:
1. Get the latest version number by Internet;
2. Take the version of the current program and compare it with the latest version.
If checking to a new version is released, open the download page (as for direct download updates, this article is not discussed).
For the first question, the easiest solution is to post a new version software on the website, publish a file that records the version number. When the software is checked (for example, when the program is started), this file is downloaded via the Internet and read the latest version number.
Note: This method is only available for simple update, and this simple method is inappropriate for the incremental update of the virus library like anti-virus software, which is usually necessary to have the corresponding server-side program cooperation.
There are many ways to download files over the Internet, such as using Wininet API or ready-made controls. This article uses indeed TIDHTTP control as an example.
The usage of the TIDHTTP control is very simple, but there is a problem with it directly using it: the program will be blocked until the file is downloaded or connected times (such as the network is not connected). So you must put it in the thread.
In PIA-MyPhotogallery, the code I use is as follows:
/ / -------------------------------------------------------------------------------------------- ---------------------------
// Get New Version Thread
Class TgetnewVersionthread: Public TTHREAD
{
Private:
Ansistring furl;
TMFileVersion * Fver;
protected:
Void __fastcall execute ();
PUBLIC:
__fastcall tgetnewversethread (ANSISTRING AURL)
: Tthread (TRUE), FURL (AURL), FVER (New TMFileVersion ())
{
FreeOnterminate = true;
}
__fastcall ~ tgetnewversionthread () {delete fver;}
__property tmfileversion * version = {read = fver};
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
// TgetNewVersionThread
/ / -------------------------------------------------------------------------------------------- ---------------------------
Void __fastcall tgetnewversethread :: execute ()
{
Boost :: scoped_ptr
WebConn (New Tidhttp (NULL));
Boost :: scoped_ptr
SS (New TstringList ());
Try {
SS-> text = WebConn-> Get (FURL);
}
Catch (...)
{
SS-> Text = "";
}
Ansistring s = SS-> VALUES ["PIAPG"];
IF (s! = "")
Fver-> verstr = s;
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
This code is simple: create a thread, create a TIDHTTP instance in the thread, then download the file corresponding to the URL, and read the "PIAPG" version number. In order to lazy, I used the Smart Pointer - Scoped_ptr in the Boost Caller.
The method of using this thread class is as follows:
/ / -------------------------------------------------------------------------------------------- ---------------------------
// Perform: when the program starts:
If (PIAPGCFG-> AutouPD) // If you select the Check Update option, check
{
If (splashdlg) // If there is SPLASH, it is displayed in it.
{
Splashdlg-> labprogress-> caption = "Checking new version ...";
Splashdlg-> labprogress-> refresh ();
}
// Create a new version of the thread
TgetNewVersionThread * pthread = New TgetneWVersionThread ("http://ental.mentsu.com/Update.txt");
Pthread-> onterminate = getnewversiondone;
Pthread-> resume ();
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
// version file download complete or timeout
Void __fastcall tMainform :: getNewVersionDone (TOBJECT * SENDER)
{
TgetNewVersionthRead * pthread = Dynamic_cast
Sender;
Boost :: scoped_ptr
FV (New TMFileVersion ());
fv-> getversionFromFile (Application-> Exename); // read the version of the current program
IF ((pthread-> version-> compare (fv.get ())> 0) // If there is a new version, then prompt
&& (Application-> Messagebox ("Discover the updated version of the program, is it updated now?",
"New version check", MB_YESNO | MB_ICONINFORMATION) == iDyes))
{
Shellexecute (NULL, "Open", "http://ental.mentsu.com", null, null, sw_show;
PostquitMessage (0);
}
}
/ / -------------------------------------------------------------------------------------------- ---------------------------
The function of this code is detailed in the comments.
Take later the second question: Problem of the program version.
In the code above, use a class: TMFileVersion. This is a class I used to write to the executable file version number before I used Delphi. The implementation code is as follows: TMFileVersion = Class
Private
Fmajor: integer;
FMINOR: Integer;
Frelease: Integer;
FBUILD: Integer;
Function Getverstr: String;
Procedure setVerstr (averstr: string);
public
Constructor crete;
DESTRUCTOR DESTROY; OVERRIDE;
Procedure getversionFromFile (AfileName: String);
Function Compare (AVER: TMFileVersion): Integer;
Property Verstr: String Read Getverstr Write setVerstr;
END;
{TMFileVersion}
// init
Constructor TMFileVersion.create;
Begin
Inherited;
FMAJOR: = 0;
FMINOR: = 0;
FRELEASE: = 0;
FBUILD: = 0;
END;
Destructor TMFileVersion.destroy;
Begin
Inherited;
END;
// Get Version Info from a file
Procedure TMFileVersion.getVersionFromFile (AfileName: String);
Type
PVS_FIXEDFILEINFO = ^ vs_fixedfileinfo;
VAR
H: cardinal; // a Handle, Ignore
nsize: cardinal; // version info size
PDATA: POINTER; // Version Info Data
PFFIDATA: PVS_FIXEDFILEINFO; / / FIXED File Info Data
NFFISIZE: cardinal; // fixed file info size
Begin
FMAJOR: = 0;
FMINOR: = 0;
FRELEASE: = 0;
FBUILD: = 0;
IF (FileExists (AfileName).
FBUILD: = 1;
nsize: = getfileversionInfosize (Pchar (AfileName), H);
IF (nsize = 0) THEN
EXIT;
GetMem (PDATA, NSIZE);
Try
GetFileVersionInfo (Pchar (AfileName), H, NSIZE, PDATA);
IF (PDATA, '/', Pointer (PfFFIDATA), NFFISIZE)) THEN
Begin
Fmajor: = (pfFFIDATA ^ .dwfileversionms) SHR 16;
Fminor: = (pfFFIDATA ^ .dwfileversionms) and $ fff;
Frelease: = (pffidata ^ .dwfileversionls) SHR 16;
FBUILD: = (pffidata ^ .dwfileversionls) and $ fff;
Finally
FreeMem (PDATA);
END;
END;
// Compare Two Version Info
Function TMFileVersion.comPare (AVER: TMFileVersion): Integer;
VAR
N1, N2: cardinal
Begin
N1: = (Fmajor SHL 16) OR FMINOR;
With aver do
N2: = (Fmajor SHL 16) OR FMINOR;
IF (n1> n2) THEN
Result: = 1
ELSE IF (N1 Result: = -1 Else Begin N1: = (FRELEASE SHL 16) or FBuild; With aver do N2: = (Frelease SHL 16) or FBuild; IF (n1> n2) THEN Result: = 1 ELSE IF (N1 Result: = -1 Else Result: = 0; END; END; // Get / set Property - Verstr Function TMFileVersion.getVerstr: String; Begin Result: = format ('% D,%. 02d,% D,%. 02d', [FMAJOR, FMINOR, FRELEASE, FBUILD]); END; Procedure TMFileVersion.setverstr (Averstr: String); VAR Stemp: tstrings; Begin FMAJOR: = 0; FMINOR: = 0; FRELEASE: = 0; FBUILD: = 0; STEMP: = TSTRINGLIST.CREATE; Try STEMP.COMMATEXT: = averstr; Try Fmajor: = start (STEMP.STRINGS [0]); Fminor: = start (STEMP.STRINGS [1]); FRELEASE: = STRTOINT (STEMP.STRINGS [2]); FBUILD: = STRTOINT (STEMP.STRINGS [3]); Except // do nothing END; Finally STEMP.FREE; END; END; Solved these two questions, the function of automatic update check is solved. BTW: For convenience, you have changed with Delphi to rewrite and package it into a VCL control. [Mental Studio] Raptor OCT.30-04