问题
Here's my 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>
This doesn't work, because it seems like it is comparing the two values as strings. Here's the log:
[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.
If I change to type Version
, it doesn't work either:
<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>
Log:
[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.
I'm using Variables
, because I need to access the values later in my custom bootstrapper.
What am I doing wrong?
回答1:
Below the Horizontal line is my original response which I think is wrong. You define a version variable as roli09 did ie:
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
and you don't need the 'v'. You do need the v if you are doing a condition like this:
Condition="InstalledVersion >= v7.0.2.1"
So that the compiler processes the second operand as a version.
What I think happened here is in the first code snippet, we have both versions being treated as string variables. And as strings they are compared character by character and '6' < '8' so we get false.
In the second code snippet I believe we end up with two Hasp_InstalledVersion variables. The one defined in the bundle which is a "version" variable and the one defined by the RegistySearch which is a string variable. I'm am guessing that in the condition it compares both version variables so this
Hasp_InstalledVersion >= Hasp_BundleVersion
becomes
0.0.0.0 >= 7.54.8889.1
which is false.
To fix this issue, do define
<Variable Name="Hasp_BundleVersion" Type="version" Value="7.54.8889.1" />
but do not define
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
Now it should compare the string variable from the registry search to the version variable defined in in the proj file. In condition.cpp of burn, if you have a "string variable OPERATION version variable", it tries to convert the string variable to a version variable and do version comparison.
Wix burn condition evaluation is a bit confusing.
I dug into it a while ago to figure out this exact issue. I believe the issue is that you're defining the version value incorrectly.
Also, I'm not sure you can use
<Variable Name="Hasp_InstalledVersion" Type="version" Value="0.0.0.0" />
since all variables set by RegistrySearches are string variables. I'm not sure if you end up having two Hasp_InstalledVersion variables defined now since one is a "version" variable and the other is a "string" version. Without wanting to delve into the wix source I would just stick to leaving it as a non-typed variable like in your first code snippet.
Now, onto fixing your condition, in the conditional evaluation there is promotion of string variables to other types of variables depending on the format of said variables. ie: string op string will do string comparison, string op version will do version comparison.
The way you format a variable to indicate it is a version is to just put a 'v' in front of it. So, I believe your issue will be solved if you update your Hasp_BundleVersion to be
<Variable Name="Hasp_BundleVersion" Value="v7.54.8889.1" />
Or better yet, you define the version somewhere in a include file or a property file (for msbuild, then included in DefineConstants) and you can update your code to
<Variable Name="Hasp_BundleVersion" Value="v$(var.HaspBundleVersion)" />
But going this far is just a matter of preference I think.
来源:https://stackoverflow.com/questions/43097231/how-to-compare-version-variables-in-detectcondition-in-burn-wix