How to Set the Wix Installer Version to the Current Build Version

How can I set the WiX installer version to the current build version?

You could use Product/@Version="!(bind.FileVersion.FileId)" (replace FileId with the Id of the file from which you'd like to get the version number) and light.exe will populate the value with the version of the file referenced by the FileId.

WiX: how to set version from .NET Assembly?

The reason that you get the error, is that the version number is not valid as a ProductVersion for a MSI package.

<major>.<minor>.<build>

major has a maximum value of 255

minor has a maximum value of 255

build has a maximum value of 65,535

Note: If you include a fourth field in your product version, the installer ignores the fourth field.

Source:
http://msdn.microsoft.com/en-us/library/aa370859%28v=vs.85%29.aspx

Configure WiX to automatically set Product Version attribute?

I use a WiX variable from an include file that I regenerate with every build.

Since my project is a .wixproj (MSBuild/Visual Studio), I just code the version extraction and formatting right in there as a custom, inline MSBuild task and call it in the BeforeBuild target.

In the example below, I get the assembly version of the main assembly of the product. You can code it up for any version you want.

Using WiX Include and variable

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include ProductVersion.wxi?>
<Product Version="$(var.ProductVersion)" …>

</Wix>

Example ProductVersion.wxi

<Include>
<?define ProductVersion=1.0.38549?>
</Include>

I recommend including the .wxi file in the project so it's visible in the Solution View. And, since it's generated, I recommend excluding it from source control.

Edit WixProj

A .wixproj is both a Visual Studio project file and an MSBuild project file. To edit a Visual Studio project file in Visual Studio, pick a tutorial or extension.

BeforeBuild Target

MSBuild systems, including WiX's, offer BeforeBuild and AfterBuild targets, as explained in the .wixproj comments.

Just pull the target out of the comments and add a task call.

<Target Name="BeforeBuild">
<GenerateProductVersion AssemblyPath='../wherever/whatever.exe' />
</Target>

MSBuild Inline Task

Task code can be in its own MSBuild file or even DLL for reuse. Or, for a scripting approach, it can be inline.

There are 3 parts to this task:

  • File path parameter (because it would vary from project to project)
  • Extraction (with logging)
  • Include generation (to a hard-coded name in the project folder because it doesn't need to vary)

.

<UsingTask TaskName="GenerateProductVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<AssemblyPath ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System" />
<Using Namespace="System.Xml.Linq" />
<Using Namespace="System.Reflection" />
<Code Type="Fragment" Language="cs"><![CDATA[
var assemblyVersion = AssemblyName.GetAssemblyName(AssemblyPath).Version;
var productVersion = String.Format("{0}.{1}.{2}", assemblyVersion.Major, assemblyVersion.Minor, assemblyVersion.Revision);
Log.LogMessage(MessageImportance.High, "ProductVersion=" + productVersion + " extracted from assembly version of " + AssemblyPath);
new XDocument(
new XElement("Include",
new XProcessingInstruction("define", "ProductVersion=" + productVersion)))
.Save("ProductVersion.wxi");
]]></Code>
</Task>
</UsingTask>

Making EXE path more visible

All of this is hidden too well in the project file. Many project designers have a Build tab that allows entering name-value pairs into the build. That provides a mechanism to raise the path up out of the XML.

<Target Name="BeforeBuild">
<GenerateProductVersion AssemblyPath='$([System.Text.RegularExpressions.Regex]::Match(";$(DefineConstants);", ";VersionExtractionPath=(?<path>.*?);").Groups["path"].Value)' />
</Target>

Sample Image

How to get current wpf project assembly version in wix toolset bootstrapper project?

Andy is right, you will not be able to pull the version number from a .cs file as WiX does not compile or know anything to do with the C# code.

What you want to do is version your main executable file (presumably the .csproj application) using the assembly version properties. (These can be found in the project properties)

1) In the Product.wxs add said main executable as a file in the installer.

<Component Id='MainExecutable' Guid='*'>
<File Id='MainExe' Name='MainExe.exe' Source='Path-to-exe' KeyPath='yes' />
</Component>

2) Bind the version of the .msi to this main executable. This is done in the Version attribute of the Product element.

<Product Id="*" Name="My Product Name" Language="1033" Version="!(bind.FileVersion.MainExe)" Manufacturer="Debabrata" UpgradeCode="PUT-GUID-HERE">

Not that the value after the FileVersion is the ID of your file. This is important.

Now to use this version number in the bootstrapper project - the process is very similar.

1) Add the MSI to the bootstrapper.

<MsiPackage SourceFile="Path-to-msi" Id="MyMSI"> 

2) In the Version attribute of the Bundle element the binding should be.

<Bundle Name="My Bundle" Version="!(bind.packageVersion.MyMSI)">

Again, note how the ID matches.

Hope this helps!

WIX Installer: ensure successive Version numbers on build

I did manage this totally outside of WIX via the Pre-Build Build Event in VS. Just place this batch scripting in your Pre-Build box. Also managed the brownie point of additionally checking for lower version numbers than the last. It also posts Errors and Warnings in VS's Errors panel.

Sample Image

Or

Sample Image

::Error Thrown by Build Script
@echo off
setlocal ENABLEDELAYEDEXPANSION

:: SETTINGS VARS
:: exceptionOnMatchingVersion can be Warning, Error or None. Be careful of trailing spaces
set exceptionOnMatchingVersion=Error

echo ==========================
echo PRE-BUILD EVENTS
echo ==========================
echo Build Type: $(ConfigurationName)
echo Project: $(ProjectName)

echo.
echo Checking Build Assembly Version for Wix Installer Build

:: PROCESS VARS
set /p lastversion=<lastbuildversion.txt

set version=0.0.0.0
FOR /F delims^=^"^ tokens^=2 %%i in ('findstr /b /c:"[assembly: AssemblyVersion(" $(ProjectDir)\Properties\AssemblyInfo.cs') do (
set version=%%i
)

set concatVersion=0.0.0
set /a presentMajor=0
set /a presentMinor=0
set /a presentPatch=0
set /a lastMajor=0
set /a lastMinor=0
set /a lastPatch=0

for /F "tokens=1,2,3 delims=." %%a in ("%version%") do (
set concatVersion=%%a.%%b.%%c
set /a presentMajor=%%a
set /a presentMinor=%%b
set /a presentPatch=%%c
)

for /F "tokens=1,2,3 delims=." %%a in ("%lastversion%") do (
set /a lastMajor=%%a
set /a lastMinor=%%b
set /a lastPatch=%%c
)

echo Build Full Assembly Version: %version%
echo Concatinated Assembly Version: %concatVersion%
echo Last Concatinated Assembly Version: %lastversion%

set lowerVersion=False

If "$(ConfigurationName)"=="Release" (
If "%lastversion%" == "%concatVersion%" (
If NOT %exceptionOnMatchingVersion% == None (
echo.
echo ======================================================================================================================================================
echo = ALERT: The last Assembly Version is the same as this Build's Assembly Version. This causes issues with the installer. Please ammend the version number.
echo = *** YOU ARE ADVISED NOT TO DEPLOY THIS VERSION ***
echo ======================================================================================================================================================
echo.
If %exceptionOnMatchingVersion% == Warning (
echo Warning: The last Assembly Version is the same as this Build's Assembly Version. This causes issues with the installer. Please ammend the version number.
)
If %exceptionOnMatchingVersion% == Error (
echo Error: The last Assembly Version is the same as this Build's Assembly Version. This causes issues with the installer. Please ammend the version number. BUILD STOPPED.
exit 1
)
)

) else (

if %presentPatch% LSS %lastPatch% (
if %presentMinor% LEQ %lastMinor% (
set "lowerVersion=True"
)
) else (

if %presentMinor% LSS %lastMinor% (
if %presentMajor% LEQ %lastMajor% (
set "lowerVersion=True"
)
) else (

if %presentMajor% LSS %lastMajor% (
set "lowerVersion=True"
)
)
)

if "!lowerVersion!"=="True" (
echo.
echo ======================================================================================================================================================
echo = FATAL EXCEPTION: You are trying to build the assembly to a lower version numer. Please check your numbering. BUILD STOPPED..
echo = *** YOU ARE ADVISED NOT TO DEPLOY THIS VERSION ***
echo ======================================================================================================================================================
echo.
echo Error: You are trying to build the assembly to a lower version numer. Please check your numbering. BUILD STOPPED. This version: %concatVersion%. Last Version: %lastversion%
exit 1
) else (
echo ======================================================================================================================================================
echo = VERSION NUMBER VALID: Proceeding to build. \o/
echo ======================================================================================================================================================
)

)
)

:: echo Lower Version: %lowerVersion%

echo %concatVersion%> lastbuildversion.txt

Modifying product version in Wix

If you can't bind/infer from your assembly then you will need to have your build automation pass a wix variable into candle.exe and use that instead of your bind statement.

In a managed code / vsts / tfs environment my typical flow is that the build definition is the source of truth and it increments and sets a buildnumber during the build. A powershell script updates all the AssemblyFileVersion attributes across my AssemblyInfo files based on this and my wixproj (votive/msbuild) does a regex match on this variable to pass it through to candle.

Automatically update version info in wix installer

What you can do is create a c/c++ program which generates a file Version.wxi which looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductVersion.Major="4"?>
<?define ProductVersion.Minor="4"?>
<?define ProductVersion.Revision="8"?>
<?define ProductVersion.Build="33"?>
<?define ProductVersion="4.4.8.33"?>
....
</Include>

Then you can include and use those version numbers in the main wxs file:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include Version.wxi ?>
<?define UpgradeCode="GUID"?>
<Product Id="*"
Name="$(var.ProductName) $(var.ProductVersion.Major).$(var.ProductVersion.Minor)"
Version="$(var.ProductVersion)" Language="1033"
Manufacturer="$(var.Company)" UpgradeCode="$(var.UpgradeCode)">

Generate the Version.wxi just before you compile your wix project. For example modify the .wixproj file to add a target which does that.

WIX: don't show build number from [ProductVersion]

Thank you @zett42, your comment pointed me out in the right direction - I created a Wix Preprocessor Extension, following the documentation here: http://wixtoolset.org/documentation/manual/v3/wixdev/extensions/extension_development_preprocessor.html

Here are the classes I created:

public class MaterialiserExtension : WixExtension
{
private MaterialiserPreprocessorExtension preprocessorExtension;

public override PreprocessorExtension PreprocessorExtension
{
get
{
if (this.preprocessorExtension == null)
{
this.preprocessorExtension = new MaterialiserPreprocessorExtension();
}

return this.preprocessorExtension;
}
}
}

public class MaterialiserPreprocessorExtension : PreprocessorExtension
{
private static string[] prefixes = { "versionUtil" };
public override string[] Prefixes { get { return prefixes; } }

public override string EvaluateFunction(string prefix, string function, string[] args)
{
string result = null;
switch (prefix)
{
case "versionUtil":
switch (function)
{
case "ToString":
if (0 < args.Length)
{
result = Version.Parse(args[0]).ToString(args.Length >1 && args[1] != null ? int.Parse(args[1]) : 4);
}
else
{
result = String.Empty;
}
break;
}
break;
}
return result;
}
}

One thing that was not immediately obvious - in my Visual Studio Wix project, I had to add
-ext "$(SolutionDir)Materialiser.Wix\bin\Release\Materialiser.Wix.dll" to Properties (Alt+Enter) > Tool Settings > Compiler (candle) and the same in Linker (light).

To use, it is very simple:
in my .wxs file I define a property like this:

<?define ProductVersion="4.6.0.5" ?>

Then I use it in Product like this:

<Product Version="$(var.ProductVersion)" .. >

And then I create anew property like this:

<Property Id="VersionWithNoBuildNumber" Value="$(versionUtil.ToString([ProductVersion], 3))" />

and in my .wxl file I use it normally:

<String Id="WelcomeDlgTitle">{\WixUI_Font_Bigger}Welcome to the [ProductName] v[VersionWithNoBuildNumber] Setup Wizard</String>

I hope this helps someone else too :p



Related Topics



Leave a reply



Submit