我想开发一个安装包,用于有条件地升级现有包。我想根据要安装的版本检查现有软件版本。为此,我必须比较版本字符串。
如何在 Inno 设置脚本中将字符串值转换为数值?
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Blah blah', 'Version', version)
version = 'V1.R2.12';
numVersion := ??string_to_numerical_value??(version);
我想开发一个安装包,用于有条件地升级现有包。我想根据要安装的版本检查现有软件版本。为此,我必须比较版本字符串。
如何在 Inno 设置脚本中将字符串值转换为数值?
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Blah blah', 'Version', version)
version = 'V1.R2.12';
numVersion := ??string_to_numerical_value??(version);
这有点棘手,因为您希望正确处理“V1.R2.12”和“V0.R15.42”之类的版本 - 在另一个答案中进行简单转换,您将得到 1212 和 1542,这不会比较您期望的方式。
您需要确定版本号的每个部分可以有多大,并将这些部分乘以该值以获得正确的结束号。像这样的东西:
[Code]
function string_to_numerical_value(AString: string; AMaxVersion: LongWord): LongWord;
var
InsidePart: boolean;
NewPart: LongWord;
CharIndex: integer;
c: char;
begin
Result := 0;
InsidePart := FALSE;
// this assumes decimal version numbers !!!
for CharIndex := 1 to Length(AString) do begin
c := AString[CharIndex];
if (c >= '0') and (c <= '9') then begin
// new digit found
if not InsidePart then begin
Result := Result * AMaxVersion + NewPart;
NewPart := 0;
InsidePart := TRUE;
end;
NewPart := NewPart * 10 + Ord(c) - Ord('0');
end else
InsidePart := FALSE;
end;
// if last char was a digit the last part hasn't been added yet
if InsidePart then
Result := Result * AMaxVersion + NewPart;
end;
您可以使用以下代码对此进行测试:
function InitializeSetup(): Boolean;
begin
if string_to_numerical_value('V1.R2.12', 1) < string_to_numerical_value('V0.R15.42', 1) then
MsgBox('Version ''V1.R2.12'' is not as recent as version ''V0.R15.42'' (false)', mbConfirmation, MB_OK);
if string_to_numerical_value('V1.R2.12', 100) > string_to_numerical_value('V0.R15.42', 100) then
MsgBox('Version ''V1.R2.12'' is more recent than version ''V0.R15.42'' (true)', mbConfirmation, MB_OK);
Result := FALSE;
end;
您是否通过 10、100 或 1000AMaxVersion
取决于您的版本号部分的数量和范围。请注意,您不能溢出LongWord
结果变量,其最大值为 2^32 - 1。
我还没有尝试过(而且我的 Pascal 知识有点生疏),但类似下面的东西应该可以工作:
function NumericVersion(s: String): Integer;
var
i: Integer;
s1: String;
begin
s1 := '';
for i := 0 to Length(s)-1 do
if (s[i] >= '0') and (s[i] <= '9') then
s1 := s1 + s[i];
Result := StrToIntDef(s1, 0);
end;
i
请不要因为我不确定它是否从零开始(s[0]
如果它是“帕斯卡字符串”,可能包含字符串的长度),所以您必须使用开始和结束值。
我在注册表中实现了两个版本字符串(实际上是一个字符串和一个 dword 值)以克服复杂性。
displayversion="v1.r1.0"
version="10100" (=1*10^4 + 1*10^2 + 0*10^0)
这很简单。虽然不是这个问题的答案,但是当面临复杂性时,人们可能会反过来思考,这可以通过更简单的方式来避免。