【问题标题】:Compare version strings in Inno Setup在 Inno Setup 中比较版本字符串
【发布时间】:2016-06-15 03:34:47
【问题描述】:

我正在读取一个 INF 文件的值,现在我需要将它与安装程序版本进行比较,但是当我编译时出现错误:

未知标识符: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} 已定义。

这篇文章与我之前的问题有关:Read an INF file during the Setup

如果有人可以提供帮助,我将不胜感激。

【问题讨论】:

    标签: version inno-setup pascalscript


    【解决方案1】:

    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;
    
    • 如果版本相同,则返回 0
    • 如果V1 早于V2,则返回-1
    • 如果V1V2 新,则返回1
    • 1.12 被认为比 1.1 更新。
    • 1.1 被认为与 1.1.0 相同。
    • 当版本在语法上无效(仅允许数字和点)时引发异常。

    Inno Setup 6.1 beta 支持与它的ComparePackedVersion function 原生比较版本(使用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

    【讨论】:

    • 你帮了我很多,谢谢!它完美地工作
    • +1。我将版本号提取移至function NextIntFromVersion(var S: string): Integer;,然后在CompareVersion 中的while 循环中我只有Result := NextIntFromVersion(V1) - NextIntFromVersion(V2);。它会稍微改变返回值:对于早于 V2V1,您只会得到负数,对于比 V2 新的 V1 - 正数。除此之外,它的工作原理相同,并且更短一些。 :)
    • 如果有人需要它,你可以避免异常并假设0如果你用StrToIntDef替换每个StrToInt(使用0作为第二个参数)。
    【解决方案2】:

    我想出了这个解决方案,它通过使用递归来更短一些。我把它写成一个过程,以便正确地返回递归的结果。也许我的参数使用并不完美,但它确实有效。

    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;
    

    用法:VerStrCompare(String1,String2,Result)
    如果两个字符串是相同的点分十进制版本,则 Result=0。
    Result=1 如果 String1 比 String2 更新(更高版本)
    Result=-1 如果 String1 比 String2 旧(低版本)

    【讨论】:

      猜你喜欢
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 2023-03-09
      • 2011-11-11
      相关资源
      最近更新 更多