如何在 burn (wix) 中比较 DetectCondition 中的版本变量
how to compare version variables in DetectCondition in burn (wix)
这是我的 Fragment
<Fragment>
<Variable Name="Hasp_BundleVersion" Value="7.54.8889.1" />
<Variable Name="Hasp_IsInstalled" />
<Variable Name="Hasp_InstalledVersion" />
<util:RegistrySearch Id="Hasp_IsInstalled"
Variable="Hasp_IsInstalled"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="exists" />
<util:RegistrySearch Condition="Hasp_IsInstalled"
After="Hasp_IsInstalled"
Variable="Hasp_InstalledVersion"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="value" />
<PackageGroup Id="Hasp">
<ExePackage Id="Hasp"
DisplayName="Hasp"
SourceFile="setups\HASPUserSetup.exe"
Compressed="yes"
DetectCondition="Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion"
InstallCommand="/s /v/qn"
PerMachine="yes"
Permanent="yes" />
</PackageGroup>
</Fragment>
这不起作用,因为它似乎是将两个值作为字符串进行比较。这是日志:
[0A74:0A4C][2017-03-29T16:29:02]i000: Initializing string variable 'Hasp_BundleVersion' to value '7.54.8889.1'
[0A74:0A4C][2017-03-29T16:29:02]i000: Setting numeric variable 'Hasp_IsInstalled' to value 1
[0A74:0A4C][2017-03-29T16:29:02]i000: Setting string variable 'Hasp_InstalledVersion' to value '7.54.66980.1'
[0A74:0A4C][2017-03-29T16:29:02]i052: Condition 'Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion' evaluates to false.
如果我改为键入 Version
,它也不起作用:
<Fragment>
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
<Variable Name="Hasp_IsInstalled" />
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
<util:RegistrySearch Id="Hasp_IsInstalled"
Variable="Hasp_IsInstalled"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="exists" />
<util:RegistrySearch Condition="Hasp_IsInstalled"
After="Hasp_IsInstalled"
Variable="Hasp_InstalledVersion"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="value" />
<PackageGroup Id="Hasp">
<ExePackage Id="Hasp"
DisplayName="Hasp"
SourceFile="setups\HASPUserSetup.exe"
Compressed="yes"
DetectCondition="Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion"
InstallCommand="/s /v/qn"
PerMachine="yes"
Permanent="yes" />
</PackageGroup>
</Fragment>
日志:
[1B40:0CEC][2017-03-29T16:42:23]i000: Initializing version variable 'Hasp_BundleVersion' to value '7.54.8889.1'
[1B40:0CEC][2017-03-29T16:42:23]i000: Initializing version variable 'Hasp_InstalledVersion' to value '0.0.0.0'
[1B40:0CEC][2017-03-29T16:42:23]i000: Setting numeric variable 'Hasp_IsInstalled' to value 1
[1B40:0CEC][2017-03-29T16:42:23]i000: Setting string variable 'Hasp_InstalledVersion' to value '7.54.66980.1'
[1B40:0CEC][2017-03-29T16:42:23]i052: Condition 'Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion' evaluates to false.
我正在使用 Variables
,因为稍后我需要在我的自定义引导程序中访问这些值。
我做错了什么?
水平线以下是我认为错误的原始回复。
您像 roli09 那样定义版本变量,即:
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
而且您不需要 'v'。如果您正在执行这样的条件,则确实需要 v:
Condition="InstalledVersion >= v7.0.2.1"
以便编译器将第二个操作数作为版本处理。
我认为这里发生的是第一个代码片段,我们将两个版本都视为字符串变量。作为字符串,它们逐个字符进行比较,'6' < '8' 所以我们得到 false。
在第二个代码片段中,我相信我们最终得到了两个 Hasp_InstalledVersion 变量。捆绑包中定义的是 "version" 变量,RegistySearch 定义的是字符串变量。我猜测在这种情况下它比较了两个版本变量所以这个
Hasp_InstalledVersion >= Hasp_BundleVersion
变成
0.0.0.0 >= 7.54.8889.1
这是错误的。
要解决此问题,请定义
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
但不定义
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
现在它应该将注册表搜索中的字符串变量与 proj 文件中定义的版本变量进行比较。在burn的condition.cpp中,如果你有一个"string variable OPERATION version variable",它会尝试将字符串变量转换为版本变量并进行版本比较。
Wix 刻录条件评估有点混乱。
我不久前深入研究了这个问题。我认为问题在于您错误地定义了版本值。
此外,我不确定您是否可以使用
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
因为 RegistrySearches 设置的所有变量都是字符串变量。我不确定您现在是否最终定义了两个 Hasp_InstalledVersion 变量,因为一个是 "version" 变量,另一个是 "string" 版本。不想深入研究 wix 源代码,我只是坚持将其保留为非类型化变量,就像在您的第一个代码片段中一样。
现在,在修复您的条件时,在条件评估中,根据所述变量的格式将字符串变量提升为其他类型的变量。即:string op string 将进行字符串比较,string op version 将进行版本比较。
格式化变量以表明它是一个版本的方法是在它前面放一个 'v'。所以,我相信如果您将 Hasp_BundleVersion 更新为
,您的问题就会得到解决
<Variable Name="Hasp_BundleVersion" Value="v7.54.8889.1" />
或者更好的是,您在包含文件或 属性 文件中的某处定义版本(对于 msbuild,然后包含在 DefineConstants 中)并且您可以将代码更新为
<Variable Name="Hasp_BundleVersion" Value="v$(var.HaspBundleVersion)" />
但我认为走到这一步只是个人喜好问题。
这是我的 Fragment
<Fragment>
<Variable Name="Hasp_BundleVersion" Value="7.54.8889.1" />
<Variable Name="Hasp_IsInstalled" />
<Variable Name="Hasp_InstalledVersion" />
<util:RegistrySearch Id="Hasp_IsInstalled"
Variable="Hasp_IsInstalled"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="exists" />
<util:RegistrySearch Condition="Hasp_IsInstalled"
After="Hasp_IsInstalled"
Variable="Hasp_InstalledVersion"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="value" />
<PackageGroup Id="Hasp">
<ExePackage Id="Hasp"
DisplayName="Hasp"
SourceFile="setups\HASPUserSetup.exe"
Compressed="yes"
DetectCondition="Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion"
InstallCommand="/s /v/qn"
PerMachine="yes"
Permanent="yes" />
</PackageGroup>
</Fragment>
这不起作用,因为它似乎是将两个值作为字符串进行比较。这是日志:
[0A74:0A4C][2017-03-29T16:29:02]i000: Initializing string variable 'Hasp_BundleVersion' to value '7.54.8889.1'
[0A74:0A4C][2017-03-29T16:29:02]i000: Setting numeric variable 'Hasp_IsInstalled' to value 1
[0A74:0A4C][2017-03-29T16:29:02]i000: Setting string variable 'Hasp_InstalledVersion' to value '7.54.66980.1'
[0A74:0A4C][2017-03-29T16:29:02]i052: Condition 'Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion' evaluates to false.
如果我改为键入 Version
,它也不起作用:
<Fragment>
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
<Variable Name="Hasp_IsInstalled" />
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
<util:RegistrySearch Id="Hasp_IsInstalled"
Variable="Hasp_IsInstalled"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="exists" />
<util:RegistrySearch Condition="Hasp_IsInstalled"
After="Hasp_IsInstalled"
Variable="Hasp_InstalledVersion"
Root="HKLM"
Key="SOFTWARE\Aladdin Knowledge Systems\HASP\Driver\Installer"
Value="Version"
Result="value" />
<PackageGroup Id="Hasp">
<ExePackage Id="Hasp"
DisplayName="Hasp"
SourceFile="setups\HASPUserSetup.exe"
Compressed="yes"
DetectCondition="Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion"
InstallCommand="/s /v/qn"
PerMachine="yes"
Permanent="yes" />
</PackageGroup>
</Fragment>
日志:
[1B40:0CEC][2017-03-29T16:42:23]i000: Initializing version variable 'Hasp_BundleVersion' to value '7.54.8889.1'
[1B40:0CEC][2017-03-29T16:42:23]i000: Initializing version variable 'Hasp_InstalledVersion' to value '0.0.0.0'
[1B40:0CEC][2017-03-29T16:42:23]i000: Setting numeric variable 'Hasp_IsInstalled' to value 1
[1B40:0CEC][2017-03-29T16:42:23]i000: Setting string variable 'Hasp_InstalledVersion' to value '7.54.66980.1'
[1B40:0CEC][2017-03-29T16:42:23]i052: Condition 'Hasp_IsInstalled AND Hasp_InstalledVersion >= Hasp_BundleVersion' evaluates to false.
我正在使用 Variables
,因为稍后我需要在我的自定义引导程序中访问这些值。
我做错了什么?
水平线以下是我认为错误的原始回复。 您像 roli09 那样定义版本变量,即:
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
而且您不需要 'v'。如果您正在执行这样的条件,则确实需要 v:
Condition="InstalledVersion >= v7.0.2.1"
以便编译器将第二个操作数作为版本处理。
我认为这里发生的是第一个代码片段,我们将两个版本都视为字符串变量。作为字符串,它们逐个字符进行比较,'6' < '8' 所以我们得到 false。
在第二个代码片段中,我相信我们最终得到了两个 Hasp_InstalledVersion 变量。捆绑包中定义的是 "version" 变量,RegistySearch 定义的是字符串变量。我猜测在这种情况下它比较了两个版本变量所以这个
Hasp_InstalledVersion >= Hasp_BundleVersion
变成
0.0.0.0 >= 7.54.8889.1
这是错误的。
要解决此问题,请定义
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
但不定义
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
现在它应该将注册表搜索中的字符串变量与 proj 文件中定义的版本变量进行比较。在burn的condition.cpp中,如果你有一个"string variable OPERATION version variable",它会尝试将字符串变量转换为版本变量并进行版本比较。
Wix 刻录条件评估有点混乱。
我不久前深入研究了这个问题。我认为问题在于您错误地定义了版本值。
此外,我不确定您是否可以使用
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
因为 RegistrySearches 设置的所有变量都是字符串变量。我不确定您现在是否最终定义了两个 Hasp_InstalledVersion 变量,因为一个是 "version" 变量,另一个是 "string" 版本。不想深入研究 wix 源代码,我只是坚持将其保留为非类型化变量,就像在您的第一个代码片段中一样。
现在,在修复您的条件时,在条件评估中,根据所述变量的格式将字符串变量提升为其他类型的变量。即:string op string 将进行字符串比较,string op version 将进行版本比较。
格式化变量以表明它是一个版本的方法是在它前面放一个 'v'。所以,我相信如果您将 Hasp_BundleVersion 更新为
,您的问题就会得到解决<Variable Name="Hasp_BundleVersion" Value="v7.54.8889.1" />
或者更好的是,您在包含文件或 属性 文件中的某处定义版本(对于 msbuild,然后包含在 DefineConstants 中)并且您可以将代码更新为
<Variable Name="Hasp_BundleVersion" Value="v$(var.HaspBundleVersion)" />
但我认为走到这一步只是个人喜好问题。