In v3, the Burn engine uses version numbers as
QWORDs to drive some of its most critical functionality.
In the real world, versions can't always be parsed into a
At its most basic level, Burn needs to use strings for versions.
In order to perform comparisons, Burn needs to a new way to parse versions. The basic idea is to use NuGet's implementation of SemVer with some variations to keep v3 Burn functionality.
Simple versions take the form
Revision are unsigned 32-bit numbers.
Revision are optional.
Valid examples are
Invalid examples are
A pre-release version is a simple version followed by a hyphen followed by a series of dot separated identifiers. These identifiers may only contain ASCII alphanumeric characters or a hyphen (
Valid examples are
Invalid examples are
Build metadata is optional, and can be added to simple versions and pre-release versions.
Build metadata starts with a plus sign.
While any characters are allowed, characters other than
[0-9a-zA-Z-_.+] are discouraged since Burn can't parse them in a condition expression.
When not in strict mode, invalid versions are parsed as much as possible and then the rest is treated as build metadata. The version is also marked as invalid.
Versions must be less than 2,147,483,647 characters.
Versions may begin with
The precedence rules mostly follow NuGet.
The Major.Minor.Patch.Revision part is compared first, just like v3 Burn.
Undefined fields are treated as zero.
220.127.116.11 > 1.2.3,
18.104.22.168 = 1.2.3,
0.0 = 0.
Next, ReleaseLabels are compared as specified in the SemVer 2.0 spec except string comparisons are done case-insensitive.
Next, the invalid flag is compared.
0.0 > @#$%^&*,
0.0 > 0.0..1,
2.0.-1 > 1.0,
1-1 > 1-2_3.
Finally, if the versions are invalid then Metadata is compared as a case-insensitive string comparison.
The main change to the Burn API is that all places that were using a
QWORD for a version will now use a
EvaluateCondition engine method/message can be used to compare versions.
The details of the parsed version will not be available to the BA, they will be internal to Burn.
This is because Burn is not the source of truth of how the version is supposed to be evaluated.
The code will be available in
verutil (and WixToolset.Mba.Core) if the BA would like to parse the version like Burn.
The condition expression parser for versions will be updated to accept the characters
>< operators will be removed when comparing versions, since they are no longer simple
When a version variable is coerced into a numeric value, then the version string is parsed as a number (just like when coercing a string variable into a number). This will fail for most versions.
When a numeric variable is coerced into a version value, then the value is split into a version using the v3 logic. The highest word is Major, the next word is Minor, the next word is Patch, and the lowest word is Revision.
Add a new
CompareVersions method for a more convenient way to compare versions:
STDMETHOD(CompareVersions)( __in_z LPCWSTR wzVersionLeft, __in_z LPCWSTR wzVersionRight, __out int* pnResult ) = 0;
Major: 1 Minor: 0 Patch: 0 Revision: 0 ReleaseLabels:  (empty) Metadata: "" (empty) Invalid: false
Major: 1 Minor: 2 Patch: 3 Revision: 4 ReleaseLabels: [2, "a", 22] Metadata: "abcdef" Invalid: false
Major: 100 Minor: 0 Patch: 0 Revision: 0 ReleaseLabels:  (empty) Metadata: "-2.0" Invalid: true
Major: 1 Minor: 0 Patch: 0 Revision: 0 ReleaseLabels:  Metadata: "" (empty) Invalid: false
Major: 2 Minor: 0 Patch: 0 Revision: 0 ReleaseLabels:  (empty) Metadata: "9999999999999999999999999999999999999.0.0" Invalid: true
22.214.171.124 > 1.2.3 126.96.36.199 = 1.2.3 1.0-2.0 > 1.0-1.19 1.0-2.0 < 1.0-19 10.-4.0 > 10.-2.0 0 > "" (empty string) 0.0.1-a > 0-2 0.0.1-a < 1-2 0.01-a.1 = 0.1.0-a.1 0.1-a.b.0 = 0.1.0-a.b.000 1.2.3+abc = 1.2.3+xyz 1.2.3+abcd > 1.2.3.-abcd 10.20.30.40 = v10.20.30.40 4294967295.4294967295.4294967295.4294967295 > 4294967296.4294967296.4294967296.4294967296
The behavior for invalid versions is completely arbitrary, but needs to be defined.
Allowing Bundles to author SemVer is out of scope of this issue.