1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
| unit AutoUpdateImpl;
interface
uses IdHTTP, SysUtils;
type
EAutoUpdate = class(exception);
EAutoUpdateMissing = class(EAutoUpdate);
EAutoUpdateInvalidUpdateInfoDocument = Class(EAutoUpdate);
TFileVersionInfo = record
FileVersion: array[0..1] of cardinal;
ProductVersion: array[0..1] of cardinal;
end;
function GetFileVersion(FileName: string; var FileInfo: TFileVersionInfo): Boolean;
function AutoUpdate_CheckEXE(EXEFileName, VersionInfoURL: String; Var UpdateURL, NewVersionInfo: String; Var CurrentVersion, Latestversion: TFileVersionInfo): Boolean; overload;
function AutoUpdate_CheckEXE(EXEFileName, VersionInfoURL: String; Var UpdateURL, NewVersionInfo: String; Var CurrentVersion, Latestversion: TFileVersionInfo; ProxyServer, ProxyUsername, ProxyPassword: string; ProxyPort: Integer): Boolean; overload;
procedure AutoUpdate_WriteEXEVersionInfoFile(EXEFileName, TargetFileName, UpdateURL, NewVersionInfo, NewVersionInfoURL: string);
implementation
{$IFDEF MSWINDOWS}
uses classes, Windows, Forms;
{$ELSE}
uses classes, QForms, SysUtils;
{$ENDIF}
resourcestring
STR_EX_VERSION_INFO_MISSING = 'Cannot extract version informations from "%s"';
STR_EX_INVALID_VERSION_INFO_STRING = 'The version info string "%s" could not be parsed';
STR_CANNOT_GET_NEW_VERSION_DOCUMENT = 'Cannot get the information page for the new version at URL "%s".'#13#10'Exception %s: "%s"';
const
STR_LATEST_VERSION = 'LatestVersion';
STR_UPDATE_URL = 'UpdateURL';
STR_NEW_VERSION_INFO = 'NewVersionInfo';
STR_NEW_VRESION_INFO_URL = 'NewVersionInfoURL';
function VersionInfoToStr(VersionInfo: TFileversionInfo): string;
begin
result := Format( '%d.%d.%d.%d', [versionInfo.ProductVersion[0], versionInfo.ProductVersion[1], versionInfo.FileVersion[0], versionInfo.FileVersion[1]]);
end;
function StrToVersionInfoStr(Src: String): TFileversionInfo;
var
StartPos, EndPos: Integer;
SrcLength: Integer;
AVersionInfoNumber, VersionInfoTarget: Integer;
begin
try
StartPos := 1;
VersionInfoTarget := 0;
SrcLength := Length(Src);
for EndPos := 1 to Length(Src) do // Iterate
begin
if (Src[EndPos] = '.') or (EndPos=SrcLength) then
begin
// get the data
if (EndPos=SrcLength) then
AVersionInfoNumber := StrToInt(Copy(Src, StartPos, EndPos - StartPos + 1))
else
AVersionInfoNumber := StrToInt(Copy(Src, StartPos, EndPos - StartPos));
// Update the starting position
StartPos := EndPos + 1;
// Update the result
case VersionInfoTarget of //
0:
result.ProductVersion[0] := AVersionInfoNumber;
1:
result.ProductVersion[1] := AVersionInfoNumber;
2:
result.FileVersion[0] := AVersionInfoNumber;
3:
result.FileVersion[1] := AVersionInfoNumber;
end; // case
inc(VersionInfoTarget);
if VersionInfoTarget > 3 then
Break;
end;
end; // for
except
raise EAutoUpdateInvalidUpdateInfoDocument.createFmt(STR_EX_INVALID_VERSION_INFO_STRING, [Src]);
end;
end;
procedure AutoUpdate_WriteEXEVersionInfoFile(EXEFileName, TargetFileName, UpdateURL, NewVersionInfo, NewVersionInfoURL: string);
var
CurrentVersion: TFileVersionInfo;
VersionInfoFile: TStringList;
begin
// get current file version;
if EXEFileName = '' then
EXEFileName := Application.ExeName;
if not GetFileVersion(Application.ExeName, CurrentVersion) then
raise EAutoUpdateMissing.CreateFmt(STR_EX_VERSION_INFO_MISSING, [EXEFileName]);
// Create the information
VersionInfoFile := TStringList.Create;
try
VersionInfoFile.Values[STR_LATEST_VERSION] := VersionInfoToStr(CurrentVersion);
VersionInfoFile.Values[STR_UPDATE_URL] := UpdateURL;
if Trim(NewVersionInfo) <> '' then
VersionInfoFile.Values[STR_NEW_VERSION_INFO] := NewVersionInfo
else
VersionInfoFile.Values[STR_NEW_VRESION_INFO_URL] := NewVersionInfoURL;
// Save the file
VersionInfoFile.SaveToFile(TargetFileName);
finally
VersionInfoFile.Free;
end;
end;
function AutoUpdate_CheckEXE(EXEFileName, VersionInfoURL: String; Var UpdateURL, NewVersionInfo: String; Var CurrentVersion, Latestversion: TFileVersionInfo): Boolean; overload;
begin
result := AutoUpdate_CheckEXE(EXEFileName, VersionInfoURL, UpdateURL, NewVersionInfo, CurrentVersion, Latestversion, '','','', 0);
end;
function AutoUpdate_CheckEXE(EXEFileName, VersionInfoURL: String; Var UpdateURL, NewVersionInfo: String; Var CurrentVersion, Latestversion: TFileVersionInfo; ProxyServer, ProxyUsername, ProxyPassword: string; ProxyPort: Integer): Boolean; overload;
var
NewVersionInfoURL: string;
IdHTTP: TIdHTTP;
Updatedata: TStringList;
CurrentVersionStr: String;
begin
// Get the version info string of the current EXE file
if EXEFileName='' then
EXEFileName := Application.ExeName;
if not GetFileVersion(Application.ExeName, CurrentVersion) then
raise EAutoUpdateMissing.CreateFmt(STR_EX_VERSION_INFO_MISSING, [EXEFileName]);
CurrentVersionStr := VersionInfoToStr(CurrentVersion);
IdHTTP := TIdHTTP.Create(nil);
try
// handle the redirections
IdHTTP.HandleRedirects := true;
// Setup the proxy if there is one
if ProxyServer <> '' then
begin
IdHTTP.ProxyParams.ProxyServer := ProxyServer;
IdHTTP.ProxyParams.ProxyPort := ProxyPort;
IdHTTP.ProxyParams.ProxyUsername := ProxyUsername;
IdHTTP.ProxyParams.ProxyPassword := ProxyPassword;
end;
// Connect to the page
Updatedata := TStringList.Create;
try
Updatedata.Text := IdHTTP.Get(VersionInfoURL);
Latestversion := StrToVersionInfoStr(Updatedata.values[STR_LATEST_VERSION]);
// Compare the local and remote version information
result := not AnsiSametext(VersionInfoToStr(Latestversion), CurrentVersionStr);
UpdateURL := Updatedata.Values[STR_UPDATE_URL];
NewVersionInfo := Updatedata.Values[STR_NEW_VERSION_INFO];
if trim(NewVersionInfo)='' then
begin
NewVersionInfoURL := Updatedata.Values[STR_NEW_VRESION_INFO_URL];
if trim(NewVersionInfoURL) <> '' then
begin
try
// statements to try
NewVersionInfo := IdHTTP.Get(NewVersionInfoURL);
except
// Supress all exceptions here: if we cannot get the update info version page, it's no big deal
on e: Exception do
NewVersionInfo := Format(STR_CANNOT_GET_NEW_VERSION_DOCUMENT,[NewVersionInfoURL, e.classname, e.Message]);
end; // try/except
end;
end;
finally
Updatedata.Free;
end;
finally
IdHTTP.Free;
end;
end;
// Copyed from WindowsStuff.pas
function GetFileVersion(FileName: string; var FileInfo: TFileVersionInfo): Boolean;
{$IFDEF MSWINDOWS}
var
Buffer: pointer;
BufferSize: Cardinal;
APVSFixedFileInfo: ^TVSFixedFileInfo;
versionInfoSize: Cardinal;
begin
result := false;
BufferSize := GetFileVersionInfoSize(PChar(FileName), versionInfoSize); // Use versionInfoSize as dummy buffer
if BufferSize > 0 then
begin
versionInfoSize := 0;
Getmem(Buffer, BufferSize);
try
if GetFileVersionInfo(PChar(FileName),0, BufferSize, Buffer) then
begin
VerQueryValue(Buffer, '\', Pointer(APVSFixedFileInfo), versionInfoSize);
if APVSFixedFileInfo^.dwSignature = $FEEF04BD then
begin
FileInfo.FileVersion[0] := APVSFixedFileInfo^.dwFileVersionMS;
FileInfo.FileVersion[1] := APVSFixedFileInfo^.dwFileVersionLS;
FileInfo.ProductVersion[0] := APVSFixedFileInfo^.dwProductVersionMS;
FileInfo.ProductVersion[1] := APVSFixedFileInfo^.dwProductVersionLS;
result := true;
end;
end
else
begin
result := false;
end;
finally
FreeMem(Buffer);
end;
end;
end;
{$ELSE}
begin
Not implemented... write some code here if you know what to do... then
end;
{$ENDIF}
end. |