将 float 数据转换为 Cardinal,反之亦然,以一种友好的方式比较版本号
Convert float data to Cardinal or vice versa for a friendly way to compare version numbers
玩过一些版本后,我遇到了数据转换问题。
我正在使用 GetVersionNumbers
方法获取版本部件作为 MS 和 LS。两个输出变量都是基数类型。现在我遇到了问题——我想将它们与其他一些版本进行比较,但最后一个版本存储在 Single 中(例如 1.3)。因此,我想将 Single 转换为 Cardinal 或将 Cardinal 转换为 Single(例如,对于 Single 中的 1.3,对应的 Cardinal 为 65539)。
至于现在,我发现了一些有趣且简单的 Delphi 解决方案,它依赖于直接内存访问:
function FloatToCardinal(val: Single): Cardinal;
var
p: ^Cardinal;
begin
p:=@(val);
Result:=p^;
end;
这里的问题是 Inno Setup 显然不能以这种方式使用指针 - 它在尝试编译时为 p: ^Cardinal;
部分给出 "Identifier expected" 错误。因此,我想为 Inno Setup 调整此功能,或者寻找其他转换或比较方式。
在此问题上如有任何帮助,我们将不胜感激。
You cannot use floats for comparison reliably。版本号不是(浮动)数字。这是一个整数序列。你甚至可以拥有像 1.2.3 这样的版本,你甚至不能将其表示为浮点数。
你最好实现一些方便的实用函数,比如:
function AreVersionNumbersAtLeast(
Major, Minor, MajorAtLeast, MinorAtLeast: Cardinal): Boolean;
begin
Result :=
(Major > MajorAtLeast) or
((Major = MajorAtLeast) or (Minor >= MinorAtLeast));
end;
并像这样使用它:
if AreVersionNumbersAtLeast(Major, Minor, 1, 3) then
Log('Program is 1.3 or newer');
如果你经常使用GetVersionNumbers
返回的MS,你可以把它包装成:
function IsVersionMSAtLeast(VersionMS, MajorAtLeast, MinorAtLeast: Cardinal): Boolean;
var
Major: Cardinal;
Minor: Cardinal;
begin
Major := VersionMS shr 16;
Minor := VersionMS and $FFFF;
Result := AreVersionNumbersAtLeast(Major, Minor, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsVersionMSAtLeast(VersionMS, 1, 3) then
Log('Program is 1.3 or newer');
甚至是 shorthand 特定文件,如:
function IsFileVersionAtLeast(
FileName: string; MajorAtLeast, MinorAtLeast: Integer): Boolean;
var
VersionMS, VersionLS: Cardinal;
begin
Result :=
GetVersionNumbers(FileName, VersionMS, VersionLS) and
IsVersionMSAtLeast(VersionMS, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsFileVersionAtLeast(ExpandConstant('{app}\MyProg.exe'), 1, 3) then
Log('Program is 1.3 or newer');
如果您更喜欢 1.3 语法,请使用字符串,而不是浮点数。
使用如下函数解析字符串:
function VersionStrToNumbers(Version: string; var Major, Minor: Cardinal): Boolean;
var
V1, V2: Integer;
P: Integer;
begin
P := Pos('.', Version);
Result := (P > 0);
if Result then
begin
V1 := StrToIntDef(Copy(Version, 1, P - 1), -1);
V2 := StrToIntDef(Copy(Version, P + 1, Length(Version) - P), -1);
Result := (V1 >= 0) and (V2 >= 0);
if Result then
begin
Major := Cardinal(V1);
Minor := Cardinal(V2);
end;
end;
end;
并用它来实现一个方便的功能,例如:
function IsFileVersionAtLeastStr(FileName, Version: string): Boolean;
var
MajorAtLeast, MinorAtLeast: Cardinal;
begin
Result :=
VersionStrToNumbers(Version, MajorAtLeast, MinorAtLeast) and
IsFileVersionAtLeast(FileName, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsFileVersionAtLeast(ExpandConstant('{app}\MyProg.exe'), '1.3') then
Log('Program is 1.3 or newer');
(这只是一个概念代码,我没有测试任何这些代码)
另一种方法是计算 "MS" 并比较:
function Version(Major, Minor: Cardinal): Cardinal;
begin
Result := (Major shl 16) + Minor;
end;
像这样使用它:
if VersionMS >= Version(1, 3) then
Log('Program is 1.3 or newer');
玩过一些版本后,我遇到了数据转换问题。
我正在使用 GetVersionNumbers
方法获取版本部件作为 MS 和 LS。两个输出变量都是基数类型。现在我遇到了问题——我想将它们与其他一些版本进行比较,但最后一个版本存储在 Single 中(例如 1.3)。因此,我想将 Single 转换为 Cardinal 或将 Cardinal 转换为 Single(例如,对于 Single 中的 1.3,对应的 Cardinal 为 65539)。
至于现在,我发现了一些有趣且简单的 Delphi 解决方案,它依赖于直接内存访问:
function FloatToCardinal(val: Single): Cardinal;
var
p: ^Cardinal;
begin
p:=@(val);
Result:=p^;
end;
这里的问题是 Inno Setup 显然不能以这种方式使用指针 - 它在尝试编译时为 p: ^Cardinal;
部分给出 "Identifier expected" 错误。因此,我想为 Inno Setup 调整此功能,或者寻找其他转换或比较方式。
在此问题上如有任何帮助,我们将不胜感激。
You cannot use floats for comparison reliably。版本号不是(浮动)数字。这是一个整数序列。你甚至可以拥有像 1.2.3 这样的版本,你甚至不能将其表示为浮点数。
你最好实现一些方便的实用函数,比如:
function AreVersionNumbersAtLeast(
Major, Minor, MajorAtLeast, MinorAtLeast: Cardinal): Boolean;
begin
Result :=
(Major > MajorAtLeast) or
((Major = MajorAtLeast) or (Minor >= MinorAtLeast));
end;
并像这样使用它:
if AreVersionNumbersAtLeast(Major, Minor, 1, 3) then
Log('Program is 1.3 or newer');
如果你经常使用GetVersionNumbers
返回的MS,你可以把它包装成:
function IsVersionMSAtLeast(VersionMS, MajorAtLeast, MinorAtLeast: Cardinal): Boolean;
var
Major: Cardinal;
Minor: Cardinal;
begin
Major := VersionMS shr 16;
Minor := VersionMS and $FFFF;
Result := AreVersionNumbersAtLeast(Major, Minor, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsVersionMSAtLeast(VersionMS, 1, 3) then
Log('Program is 1.3 or newer');
甚至是 shorthand 特定文件,如:
function IsFileVersionAtLeast(
FileName: string; MajorAtLeast, MinorAtLeast: Integer): Boolean;
var
VersionMS, VersionLS: Cardinal;
begin
Result :=
GetVersionNumbers(FileName, VersionMS, VersionLS) and
IsVersionMSAtLeast(VersionMS, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsFileVersionAtLeast(ExpandConstant('{app}\MyProg.exe'), 1, 3) then
Log('Program is 1.3 or newer');
如果您更喜欢 1.3 语法,请使用字符串,而不是浮点数。
使用如下函数解析字符串:
function VersionStrToNumbers(Version: string; var Major, Minor: Cardinal): Boolean;
var
V1, V2: Integer;
P: Integer;
begin
P := Pos('.', Version);
Result := (P > 0);
if Result then
begin
V1 := StrToIntDef(Copy(Version, 1, P - 1), -1);
V2 := StrToIntDef(Copy(Version, P + 1, Length(Version) - P), -1);
Result := (V1 >= 0) and (V2 >= 0);
if Result then
begin
Major := Cardinal(V1);
Minor := Cardinal(V2);
end;
end;
end;
并用它来实现一个方便的功能,例如:
function IsFileVersionAtLeastStr(FileName, Version: string): Boolean;
var
MajorAtLeast, MinorAtLeast: Cardinal;
begin
Result :=
VersionStrToNumbers(Version, MajorAtLeast, MinorAtLeast) and
IsFileVersionAtLeast(FileName, MajorAtLeast, MinorAtLeast);
end;
并像这样使用它:
if IsFileVersionAtLeast(ExpandConstant('{app}\MyProg.exe'), '1.3') then
Log('Program is 1.3 or newer');
(这只是一个概念代码,我没有测试任何这些代码)
另一种方法是计算 "MS" 并比较:
function Version(Major, Minor: Cardinal): Cardinal;
begin
Result := (Major shl 16) + Minor;
end;
像这样使用它:
if VersionMS >= Version(1, 3) then
Log('Program is 1.3 or newer');