Inno Setup Script Sample for Version Comparison
This post talks about a sample Inno Setup script for version comparison.
An important feature that Inno Setup fails to provide is to uninstall old versions before installing a new version. When I prepared Code Beautifier Collection 6.0 Milestone 3, I started to think about this feature. Luckily because I have experienced Pascal script already, I soon found a way.
Every installer place some information in your registry in order to display an item in your Control Panel’s Add/Remove Programs. In your Inno Setup script under [Setup]
section, you should specify AppVersion
and AppID
. For example,
1
2
AppVersion=6.0.0.1004
AppID={{F768F6BA-F164-4599-BC26-DCCFC2F76855}
As a result, some registry items are added.
So in [Code]
section you can use Pascal script to do version string comparison to see if there is an older version.
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
function InitializeSetup(): Boolean;
var
oldVersion: String;
uninstaller: String;
ErrorCode: Integer;
begin
if RegKeyExists(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1') then
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1',
'DisplayVersion', oldVersion);
if (CompareVersion(oldVersion, '6.0.0.1004') < 0) then
begin
if MsgBox('Version ' + oldVersion + ' of Code Beautifier Collection is already installed. Continue to use this old version?',
mbConfirmation, MB_YESNO) = IDYES then
begin
Result := False;
end
else
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F768F6BA-F164-4599-BC26-DCCFC2F76855}_is1',
'UninstallString', uninstaller);
ShellExec('runas', uninstaller, '/SILENT', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
Result := True;
end;
end
else
begin
MsgBox('Version ' + oldVersion + ' of Code Beautifier Collection is already installed. This installer will exit.',
mbInformation, MB_OK);
Result := False;
end;
end
else
begin
Result := True;
end;
end;
Do something in InitializeSetup
gives you a chance to exit the installation if necessary.
First, I try to see if CBC was installed. Using AppID makes thing easy. Second, I read AppVersion
from registry named DisplayVersion
.
Then, I compare the read result with current version, 6.0.0.1004
.
Finally, if there is a newer or the same version installed, exit. If an older version is there, uninstall it and continue to install this new version.
Because Inno Setup does not provide version string comparison function, I wrote customized code first in Delphi 2007 and then copied the code to Inno Setup script. This is an important thing, that you can debug the code in Delphi while you cannot debug it in Inno Setup,
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
function GetNumber(var temp: String): Integer;
var
part: String;
pos1: Integer;
begin
if Length(temp) = 0 then
begin
Result := -1;
Exit;
end;
pos1 := Pos('.', temp);
if (pos1 = 0) then
begin
Result := StrToInt(temp);
temp := '';
end
else
begin
part := Copy(temp, 1, pos1 - 1);
temp := Copy(temp, pos1 + 1, Length(temp));
Result := StrToInt(part);
end;
end;
function CompareInner(var temp1, temp2: String): Integer;
var
num1, num2: Integer;
begin
num1 := GetNumber(temp1);
num2 := GetNumber(temp2);
if (num1 = -1) or (num2 = -1) then
begin
Result := 0;
Exit;
end;
if (num1 > num2) then
begin
Result := 1;
end
else if (num1 < num2) then
begin
Result := -1;
end
else
begin
Result := CompareInner(temp1, temp2);
end;
end;
function CompareVersion(str1, str2: String): Integer;
var
temp1, temp2: String;
begin
temp1 := str1;
temp2 := str2;
Result := CompareInner(temp1, temp2);
end;
These function should be placed at the beginning of [Code]
section. Currently, I do not know how to access AppID
of [Setup]
section in [Code]
section, so all version strings are hard coded. Once I find a way to do so, those hard coded strings can be replaced.
In fact, I prefer Pascal script to MSIcode in InstallAware and I will continue using Inno Setup for CBC. Pascal programming has become part of my life.
Actually I tried to search on Google before actions, and the only useful entry returned from query is a post on AgileTrack Blog. however, that approach is a complicated approach. I believe my code is simpler and make full use of existing information in your registry. BTW, you can download the full iss file from here