36

I want to include some dynamic part in the filename of the msi file my wix projects produce. This dynamic part should be controlled by variables which are part of my wix project and are declared like this:

<?define ProductVersion="7.1.0.1" ?>

Does anybody know about a way of sending that value of that wix variable to the linker to use it as a part of the output filename?

By the way: I'm using Wix3

Jan
  • 15,802
  • 5
  • 35
  • 59

8 Answers8

54

You could update the OutputName of your .wixproj and use an MSBuild variable to pass through the version number or any other variable you like.

My build script looks like this:

set PRODUCTVERSION=7.1.0.1
MSBuild.exe /p:Configuration=Debug /p:ProductVersion=%PRODUCTVERSION% Installer.wixproj

And my WiX project looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>1.0.0.0</ProductVersion>
    <ProjectGuid>{b7415c44-8d59-4ac2-b698-03e399a305e3}</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputName>Installer.$(ProductVersion)</OutputName>
    ...
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
    <WixVariables>ProductVersion=$(ProductVersion)</WixVariables>
  </PropertyGroup>
  ...
</Project>

The output would be:

Installer.7.1.0.1.msi
Charlie
  • 846
  • 7
  • 21
  • 3
    Exactly what I was looking for, thanks! Unfortunately VisualStudio does not seem to like something like `$(ProductName)` out of the box. For me scenario it was sufficient to provide a default value (primarily used for builds via VisualStudio by a human: `ApplicationSetup`) and pass a real value as @Charlie described (when run by the build server via msbuild). – CodeFox Apr 17 '14 at 13:25
  • 1
    This should be the accepted answer... was precisely what I needed (plus the addendum from @CodeFox). – Jon Mar 10 '17 at 15:46
17

The msi file name is not determined by your wix files, but by the light.exe -out switch. You can use the same value for -out and inside your wix files if you do the following in your build script, assuming it is a batch script:

  • set an environment variable with set productversion=1.2.3
  • Pass -out foo%productversion%.msi to the light.exe linker
  • use the same environment variable in your wix files as $(env.productversion)
Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
8

Open *.wixproj (example: Setup.wixproj)

Go to the end of the file.

$(Configuration) = Debug| Release …

Set path of your application on AssemblyFiles.

<Target Name="BeforeBuild">
    <GetAssemblyIdentity AssemblyFiles="..\App\bin\$(Configuration)\App.exe">
      <Output TaskParameter="Assemblies" ItemName="AsmInfo" />
    </GetAssemblyIdentity>
    <CreateProperty Value="$(SolutionName)_%(AsmInfo.Version)_$(Configuration)">
      <Output TaskParameter="Value" PropertyName="TargetName" />
    </CreateProperty>
</Target>

Output = App_1.0.0.0_Debug.msi

lsaudon
  • 1,263
  • 11
  • 24
  • I'd love a version of this answer that got the version info from a native executable, a la Powershell's `(Get-Item D:\path\to\app.exe).VersionInfo.ProductVersion`. – Keith Russell Dec 15 '20 at 19:29
5

I found a couple of great reference posts to do just this operation:

http://blog.tentaclesoftware.com/archive/2009/05/03/38.aspx

and a follow-on with a better method of creating the output file using a pre-build event:

http://blog.tentaclesoftware.com/archive/2010/08/05/99.aspx

I know the links are old, but the method is sound.

Here are the basic steps:

  • Put the version you wish to use into a file you can access from your project. I use the main executable of my installation because I also bind to that version in my wxs. In my case, since I am building with C# and use SVN, I have a template version of my assembly.cs, assembly.cs.txt, that I run subwcrev on as a pre-build event to create the assembly.cs that gets compiled into my executable (I actually do it in a separate project in my solution). Subwcrev inserts some date and revision information that I use to create a version in the form "major.minor.version.0" where I use "year.month.revision.0" for my version.

  • Now, I usually just set AssemblyFileVersion with this method, but to be able to use my version number in the wixproj build event referenced in the post above, I also need to set AssemblyVersion since that is what can be accessed with GetAssemblyIdentity. This method would be questionable if I were really using an assembly someone else links to, but for me it is OK since it is in my final application executable.

  • Follow the steps outlined in the second post (the first post discusses using the binding method for version in wxs and how to unload and edit the wixproj - valuable context for the second post).

Works like a charm!

Update some years later - it looks like the links I referenced are dead. Here is a snapshot of what I changed to make it work.

In my main product wxs file, I changed (some names have been changed or omitted to protect the innocent and the guilty):

    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
  <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
  <Component Id="ProductComponent" Guid="DF1AB3A6-17D0-4176-B3AC-C073AC47AA80">
            <RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
            <File Source="$(var.MyApp.TargetPath)" KeyPath="yes"/>
            <File Source="$(var.MyApp.ProjectDir)\bin\Release\MyData.dll"/>
            <File Source="$(var.MyApp.ProjectDir)\bin\$(var.MyApp.Configuration)\ICSharpCode.SharpZipLib.dll"/>
        </Component>
</ComponentGroup>

to

    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
  <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
  <Component Id="ProductComponent" Guid="DF1AB3A6-17D0-4176-B3AC-C073AC47AA80">
    <RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
    <File Id="MAINEXECUTABLE" Source="$(var.MyApp.TargetPath)" KeyPath="yes">
      <Shortcut Directory="ApplicationProgramsFolder" Id="MYAPPEXEAPF" Name="My App Name" Icon="MyAppIcon.exe" IconIndex="0" Advertise="yes" />
      <Shortcut Directory="ApplicationDesktopFolder" Id="MYAPPEXEADF" Name="My App Name" Icon="MyAppIcon.exe" IconIndex="0" Advertise="yes" />
    </File>
    <File Source="$(var.MyApp.ProjectDir)\bin\Release\MyData.dll"/>
    <File Source="$(var.MyApp.ProjectDir)\bin\$(var.MyApp.Configuration)\ICSharpCode.SharpZipLib.dll"/>
  </Component>
</ComponentGroup>

and up at the top I added:

  <Product Id="C86505BF-303F-4D6B-8F5F-43A57635F85D" Name="My Application Name" Language="1033" Version="!(bind.FileVersion.MAINEXECUTABLE)" Manufacturer="My Software Shop" UpgradeCode="D1C628E5-5478-4DA5-A31A-F9191D5B1544">

Note that the Version is bound to the file version of MAINEXECUTABLE, which is defined in the main product component.

I hope this helps!

GTAE86
  • 1,780
  • 3
  • 29
  • 39
  • 1
    You should copy the build targets into your answer, as you will then likely get more upvotes. This is the best answer by miles and it is getting overlooked because it doesn't seem to offer a visible solution. – Tim Long Sep 11 '18 at 00:19
  • Could not open the links provided. – MHOOS May 03 '20 at 23:51
  • This answer doesn't seem to be relevant at all - all code is related to the setting of installer version, rather than of installer file name. – Mike Rosoft Aug 24 '21 at 17:39
  • The archived links are https://web.archive.org/web/20120204191316/http://blog.tentaclesoftware.com/archive/2009/05/03/38.aspx and https://web.archive.org/web/20101128215334/http://blog.tentaclesoftware.com/archive/2010/08/05/99.aspx . The code in the blog just renames the output MSI file. – Mike Rosoft Aug 24 '21 at 17:43
2

If you have several configurations then inside .wixprj file you can do the following

<OutputName Condition="'$(Configuration)' == 'User'">User.Setup</OutputName>
<OutputName Condition="'$(Configuration)' == 'Designer'">Designerr.Setup</OutputName>
RatiboR
  • 65
  • 1
  • 6
  • where is that supposed to be placed? – Karina Kozarova Jul 09 '21 at 09:37
  • @KarinaKozarova, when you have a WIX Toolset project, created it will automatically create a file with .wxprj extension and in this file, you could define two output name ruled by the condition. – RatiboR Jul 30 '21 at 14:47
1

Since it's just a file name, why not have a post-build action that renames the file in your build script (assuming MSBuild)?

Agent_9191
  • 7,216
  • 5
  • 33
  • 57
  • Ok, that would work probably. I will try that out. But i was looking for a more direct way - or do you think this is not supported in wix? I read something about linker variables here: http://n2.nabble.com/Types-of-variables-question-td3825142.html !(wix.Name) gets what are called WixVariables (can be defined in source code with the WixVariable element, or passed on the commandline of light and/or lit in a manner similar as preprocessor variables are passed to candle). But that doesn't seem to work. – Jan Nov 06 '09 at 16:24
  • 1
    I mentioned this way since it's the quickest and simplest way to handle it. Like so many other development problems, always remember to KISS. – Agent_9191 Nov 06 '09 at 16:35
  • 11
    Renaming the MSI is a bad idea. Don't do it! http://blogs.msdn.com/b/robmen/archive/2004/12/08/278746.aspx – l33t Oct 15 '14 at 07:51
  • 1
    Thanks I33t! I was falling into the trap that is to rename msi. I would certainly lose the ability to upgrade my product if I didn't read your comment. – Leonardo Alves Machado Dec 11 '15 at 17:29
  • 2
    the blog is gone :( what did it say – Rod Mar 25 '20 at 21:37
  • For those looking for robmen's archive, I found it here: https://learn.microsoft.com/en-us/archive/blogs/robmen/why-does-changing-the-name-of-your-msi-file-require-a-major-upgrade – Tipx May 31 '21 at 19:06
0

Do the variables have to be defined in WiX? I'm building my setup binaries from MSBuild, and I've simply set the output file name to MyProject_$(Platform) -- I expect that any MSBuild variable substitution will work equally well.

Rytmis
  • 31,467
  • 8
  • 60
  • 69
-6
Product Id="GUID" Name="whatevername $(var.ProductVersion)" 
CoolBeans
  • 20,654
  • 10
  • 86
  • 101
  • 1
    This controls how the product is displayed in Add/Remove programs, not the file name of the MSI. – Rozwel Dec 28 '12 at 18:12