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

发布于 2024-07-26 21:12:03 字数 291 浏览 9 评论 0原文

我想开发一个安装包来有条件地升级现有包。 我想根据要安装的版本检查现有软件版本。 为了做到这一点,我必须比较版本字符串。

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

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

I want to develop a setup package for conditionally upgrading an existing package. I want to check the existing software version against to-be-installed version. In order to do that, I have to compare the version strings.

How can I convert the string value to a numerical value in a Inno setup script?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故人爱我别走 2024-08-02 21:12:03

这有点棘手,因为您希望正确处理“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。

This is a little more tricky, as you would want to handle versions like 'V1.R2.12' and 'V0.R15.42' correctly - with the simple conversion in the other answer you would get 1212 and 1542, which would not compare the way you would expect.

You need to decide how big each part of the version number can be, and multiply the parts by that value to get a correct end number. Something like this:

[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;

You can test this with the following code:

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;

Whether you pass 10, 100 or 1000 for AMaxVersion depends on the number and range of your version number parts. Note that you must not overflow the LongWord result variable, which has a maximum value of 2^32 - 1.

埋情葬爱 2024-08-02 21:12:03

我还没有尝试过(我的 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 的起始值和结束值用作我不确定它是否是从零开始的(如果它是“Pascal String”,则 s[0] 可能包含字符串的长度)。

I haven't tried that (and my Pascal knowledge is a bit rusty), but something like the following should work:

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;

Please not that you'll have to play with the start and end value for i as I'm not sure whether it is zero-based or not (s[0] may contain the length of the string if it is a "Pascal String").

九八野马 2024-08-02 21:12:03

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

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

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

I've implemented two version strings (actually one string and one dword value) in the registry to overcome complexity.

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

That's simple. Though not an answer to this question, however one might think the other way around when faced with complexity, which could be avoided in a simpler way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文