在 Inno Setup 中比较版本字符串
Compare version strings in Inno Setup
我正在读取 INF 文件的值,现在我需要将它与安装程序版本进行比较,但是当我编译时出现错误:
Unknown identifier: CompareVersion
怎么了?
[Code]
function GetKeyValue(const AKeyName, AFileName, ADefault: string): string;
var
I: Integer;
KeyPos: Integer;
KeyFull: string;
FileLines: TArrayOfString;
begin
Result := ADefault;
if LoadStringsFromFile(AFileName, FileLines) then
begin
KeyFull := AKeyName + '=';
for I := 0 to GetArrayLength(FileLines) - 1 do
begin
FileLines[I] := TrimLeft(FileLines[I]);
KeyPos := Pos(KeyFull, FileLines[I]);
if KeyPos > 0 then
begin
Result := Copy(FileLines[I], KeyPos + Length(AKeyName) + 1, MaxInt);
Break;
end;
end;
end;
end;
var
L2Ver2: TLabel;
procedure DirEditChange(Sender: TObject);
var
FilePath: string;
begin
FilePath := AddBackslash(WizardForm.DirEdit.Text) + 'left4dead2\steam.inf';
L2Ver2.Caption := GetKeyValue('PatchVersion', FilePath, 'N/A');
if (CompareVersion( L2Ver2.Caption, '{#MyAppOldVersion}') = 0) then
begin
...
end
end;
我在这一行有错误:
if (CompareVersion( L2Ver2.Caption, '{#MyAppOldVersion}') = 0) then
{#MyAppOldVersion}
已定义。
这个post与我之前的问题有关:Read an INF file during the Setup。
如果有人能提供帮助,我将不胜感激。
Inno Setup 中没有 CompareVersion
功能 (当前 6.1 beta 中有一个,见下文)。
您需要自己定义。
类似于:
function CompareVersion(V1, V2: string): Integer;
var
P, N1, N2: Integer;
begin
Result := 0;
while (Result = 0) and ((V1 <> '') or (V2 <> '')) do
begin
P := Pos('.', V1);
if P > 0 then
begin
N1 := StrToInt(Copy(V1, 1, P - 1));
Delete(V1, 1, P);
end
else
if V1 <> '' then
begin
N1 := StrToInt(V1);
V1 := '';
end
else
begin
N1 := 0;
end;
P := Pos('.', V2);
if P > 0 then
begin
N2 := StrToInt(Copy(V2, 1, P - 1));
Delete(V2, 1, P);
end
else
if V2 <> '' then
begin
N2 := StrToInt(V2);
V2 := '';
end
else
begin
N2 := 0;
end;
if N1 < N2 then Result := -1
else
if N1 > N2 then Result := 1;
end;
end;
- Returns
0
,如果版本相同。
- Returns
-1
,如果 V1
比 V2
.
- Returns
1
,如果 V1
比 V2
. 更新
1.12
被认为比 1.1
. 更新
1.1
被认为与 1.1.0
. 相同
- 当版本在语法上无效(只允许数字和点)时抛出异常。
Inno Setup 6.1 beta 支持版本与其 ComparePackedVersion
function (use GetPackedVersion
进行本地比较以获得所需格式的二进制版本。
单元测试:
procedure CompareVersionTest(V1, V2: string; Expected: Integer);
var
R: Integer;
M: string;
begin
M := Format('Comparing [%s] vs. [%s] - expecting %d - ', [V1, V2, Expected]);
R := CompareVersion(V1, V2);
if R <> Expected then
begin
RaiseException(M + Format('Failed - Got %d', [R]));
end
else
begin
Log(M + 'Passed');
end;
end;
procedure CompareVersionTests;
begin
CompareVersionTest('1', '1', 0);
CompareVersionTest('1.2', '1.2', 0);
CompareVersionTest('1.2.3', '1.2.3', 0);
CompareVersionTest('1', '2', -1);
CompareVersionTest('1', '3', -1);
CompareVersionTest('2', '3', -1);
CompareVersionTest('2', '1', 1);
CompareVersionTest('3', '1', 1);
CompareVersionTest('3', '2', 1);
CompareVersionTest('1', '12', -1);
CompareVersionTest('12', '2', 1);
CompareVersionTest('12', '12', 0);
CompareVersionTest('1.2', '1.3', -1);
CompareVersionTest('1.3', '1.2', 1);
CompareVersionTest('1.2', '11.2', -1);
CompareVersionTest('11.2', '1.2', 1);
CompareVersionTest('1.1', '1.12', -1);
CompareVersionTest('1.11', '1.12', -1);
CompareVersionTest('1.12', '1.1', 1);
CompareVersionTest('1.12', '1.11', 1);
CompareVersionTest('1', '1.0', 0);
CompareVersionTest('1.0', '1', 0);
CompareVersionTest('1', '1.1', -1);
CompareVersionTest('1.1', '1', 1);
CompareVersionTest('1.12.123', '1.12.124', -1);
CompareVersionTest('1.12.124', '1.12.123', 1);
CompareVersionTest('1.12.123', '1.13.1', -1);
CompareVersionTest('1.13.1', '1.12.123', 1);
CompareVersionTest('1.12.123', '1.13', -1);
CompareVersionTest('1.13', '1.12.123', 1);
CompareVersionTest('1.12', '1.13.1', -1);
CompareVersionTest('1.13.1', '1.12', 1);
end;
如果你想 运行 单元测试,只需在 InitializeSetup
中调用 CompareVersionTests
。
我想出了这个解决方案,它通过使用递归来缩短一些。我把它写成一个过程,以便 return 正确地从递归中得到结果。也许我的参数使用不完美,但它有效。
procedure VerStrCompare(S1,S2:String; var pComp:Integer);
var nE1,nE2,nV1,nV2:Integer;
begin
if (Length(S1)>0) OR (Length(S2)>0) then begin
nE1:=Pos('.',S1+'.');
nE2:=Pos('.',S2+'.');
if nE1>1 then nV1:=StrToInt(Copy(s1,1,(nE1-1))) else nV1:=0;
if nE2>1 then nV2:=StrToInt(Copy(s2,1,(nE2-1))) else nV2:=0;
if nV1=nV2 then VerStrCompare(Copy(s1,nE1+1,Length(s1)),Copy(s2,nE2+1,Length(s2)),pComp)
else if nV1>nV2 then pComp:=1
else if nV1<nV2 then pComp:=-1;
end
else pComp:=0;
end;
Usage: VerStrCompare(String1,String2,Result)
where Result=0 if both strings are the same dotted decimal versions.
Result=1 if String1 is newer (higher version) than String2
Result=-1 if String1 is older (lower version) than String2
我正在读取 INF 文件的值,现在我需要将它与安装程序版本进行比较,但是当我编译时出现错误:
Unknown identifier: CompareVersion
怎么了?
[Code]
function GetKeyValue(const AKeyName, AFileName, ADefault: string): string;
var
I: Integer;
KeyPos: Integer;
KeyFull: string;
FileLines: TArrayOfString;
begin
Result := ADefault;
if LoadStringsFromFile(AFileName, FileLines) then
begin
KeyFull := AKeyName + '=';
for I := 0 to GetArrayLength(FileLines) - 1 do
begin
FileLines[I] := TrimLeft(FileLines[I]);
KeyPos := Pos(KeyFull, FileLines[I]);
if KeyPos > 0 then
begin
Result := Copy(FileLines[I], KeyPos + Length(AKeyName) + 1, MaxInt);
Break;
end;
end;
end;
end;
var
L2Ver2: TLabel;
procedure DirEditChange(Sender: TObject);
var
FilePath: string;
begin
FilePath := AddBackslash(WizardForm.DirEdit.Text) + 'left4dead2\steam.inf';
L2Ver2.Caption := GetKeyValue('PatchVersion', FilePath, 'N/A');
if (CompareVersion( L2Ver2.Caption, '{#MyAppOldVersion}') = 0) then
begin
...
end
end;
我在这一行有错误:
if (CompareVersion( L2Ver2.Caption, '{#MyAppOldVersion}') = 0) then
{#MyAppOldVersion}
已定义。
这个post与我之前的问题有关:Read an INF file during the Setup。
如果有人能提供帮助,我将不胜感激。
Inno Setup 中没有 CompareVersion
功能 (当前 6.1 beta 中有一个,见下文)。
您需要自己定义。
类似于:
function CompareVersion(V1, V2: string): Integer;
var
P, N1, N2: Integer;
begin
Result := 0;
while (Result = 0) and ((V1 <> '') or (V2 <> '')) do
begin
P := Pos('.', V1);
if P > 0 then
begin
N1 := StrToInt(Copy(V1, 1, P - 1));
Delete(V1, 1, P);
end
else
if V1 <> '' then
begin
N1 := StrToInt(V1);
V1 := '';
end
else
begin
N1 := 0;
end;
P := Pos('.', V2);
if P > 0 then
begin
N2 := StrToInt(Copy(V2, 1, P - 1));
Delete(V2, 1, P);
end
else
if V2 <> '' then
begin
N2 := StrToInt(V2);
V2 := '';
end
else
begin
N2 := 0;
end;
if N1 < N2 then Result := -1
else
if N1 > N2 then Result := 1;
end;
end;
- Returns
0
,如果版本相同。 - Returns
-1
,如果V1
比V2
. - Returns
1
,如果V1
比V2
. 更新
1.12
被认为比1.1
. 更新
1.1
被认为与1.1.0
. 相同
- 当版本在语法上无效(只允许数字和点)时抛出异常。
Inno Setup 6.1 beta 支持版本与其 ComparePackedVersion
function (use GetPackedVersion
进行本地比较以获得所需格式的二进制版本。
单元测试:
procedure CompareVersionTest(V1, V2: string; Expected: Integer);
var
R: Integer;
M: string;
begin
M := Format('Comparing [%s] vs. [%s] - expecting %d - ', [V1, V2, Expected]);
R := CompareVersion(V1, V2);
if R <> Expected then
begin
RaiseException(M + Format('Failed - Got %d', [R]));
end
else
begin
Log(M + 'Passed');
end;
end;
procedure CompareVersionTests;
begin
CompareVersionTest('1', '1', 0);
CompareVersionTest('1.2', '1.2', 0);
CompareVersionTest('1.2.3', '1.2.3', 0);
CompareVersionTest('1', '2', -1);
CompareVersionTest('1', '3', -1);
CompareVersionTest('2', '3', -1);
CompareVersionTest('2', '1', 1);
CompareVersionTest('3', '1', 1);
CompareVersionTest('3', '2', 1);
CompareVersionTest('1', '12', -1);
CompareVersionTest('12', '2', 1);
CompareVersionTest('12', '12', 0);
CompareVersionTest('1.2', '1.3', -1);
CompareVersionTest('1.3', '1.2', 1);
CompareVersionTest('1.2', '11.2', -1);
CompareVersionTest('11.2', '1.2', 1);
CompareVersionTest('1.1', '1.12', -1);
CompareVersionTest('1.11', '1.12', -1);
CompareVersionTest('1.12', '1.1', 1);
CompareVersionTest('1.12', '1.11', 1);
CompareVersionTest('1', '1.0', 0);
CompareVersionTest('1.0', '1', 0);
CompareVersionTest('1', '1.1', -1);
CompareVersionTest('1.1', '1', 1);
CompareVersionTest('1.12.123', '1.12.124', -1);
CompareVersionTest('1.12.124', '1.12.123', 1);
CompareVersionTest('1.12.123', '1.13.1', -1);
CompareVersionTest('1.13.1', '1.12.123', 1);
CompareVersionTest('1.12.123', '1.13', -1);
CompareVersionTest('1.13', '1.12.123', 1);
CompareVersionTest('1.12', '1.13.1', -1);
CompareVersionTest('1.13.1', '1.12', 1);
end;
如果你想 运行 单元测试,只需在 InitializeSetup
中调用 CompareVersionTests
。
我想出了这个解决方案,它通过使用递归来缩短一些。我把它写成一个过程,以便 return 正确地从递归中得到结果。也许我的参数使用不完美,但它有效。
procedure VerStrCompare(S1,S2:String; var pComp:Integer);
var nE1,nE2,nV1,nV2:Integer;
begin
if (Length(S1)>0) OR (Length(S2)>0) then begin
nE1:=Pos('.',S1+'.');
nE2:=Pos('.',S2+'.');
if nE1>1 then nV1:=StrToInt(Copy(s1,1,(nE1-1))) else nV1:=0;
if nE2>1 then nV2:=StrToInt(Copy(s2,1,(nE2-1))) else nV2:=0;
if nV1=nV2 then VerStrCompare(Copy(s1,nE1+1,Length(s1)),Copy(s2,nE2+1,Length(s2)),pComp)
else if nV1>nV2 then pComp:=1
else if nV1<nV2 then pComp:=-1;
end
else pComp:=0;
end;
Usage: VerStrCompare(String1,String2,Result)
where Result=0 if both strings are the same dotted decimal versions.
Result=1 if String1 is newer (higher version) than String2
Result=-1 if String1 is older (lower version) than String2