如何在Inno Setup Scripts中将字符串版本值转换为数值?

时间:2009-07-08 11:27:41

标签: installer installation inno-setup pascal

我想开发一个用于有条件地升级现有包的安装包。我想根据待安装的版本检查现有的软件版本。为此,我必须比较版本字符串。

如何在Inno设置脚本中将字符串值转换为数值?

RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\Blah blah', 'Version', version)
version = 'V1.R2.12';
numVersion := ??string_to_numerical_value??(version);

3 个答案:

答案 0 :(得分:4)

这有点棘手,因为你想要正确处理像'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;

是否为AMaxVersion传递10,100或1000,取决于版本号部件的数量和范围。请注意,您不得溢出LongWord结果变量,该变量的最大值为2 ^ 32 - 1。

答案 1 :(得分:0)

我没有尝试过(而且我的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]可能包含字符串,如果它是“Pascal字符串”)。

答案 2 :(得分:0)

我在注册表中实现了两个版本字符串(实际上是一个字符串和一个双字值)以克服复杂性。

displayversion="v1.r1.0"
version="10100"   (=1*10^4 + 1*10^2 + 0*10^0)

这很简单。虽然不是这个问题的答案,但是当面对复杂性时,人们可能会想到另一种方式,这可以通过更简单的方式避免。