[Wix] How to use Wix to create Windows Installer files ?

October 17th, 2011 | Posted by Tom in .NET | Article | Divers | Wix | Read: 17,760

Wix is a technology that aims to help developer create Windows Installer file for the projects they’re developing. This is a very complete product but it can be a bit difficult to understand for new users. I’ll try to explain you how to create your first basic installer. I hope to be able to write more about Wix as soon as possible!

First, you need to download and install the latest version of Wix (latest stable version is 3.5, and the beta one is 3.6). Once it’s installed, just start Visual Studio and create a new project:

image

Wix projects are simple XML files (with the wxs extension) which describe the list of files that need to be copied on the target machine. They also define the various actions that can be performed during the installation (registry keys to be created, components that need to be installed, etc.).

A basic Wix file contains, at least, the following XML elements:

  1. Product: it’s used to describe the Windows Installer to be create (name, language, manufacturer, etc.)
  2. Package: this element contains the information that goes in the MSI’s summary information stream
  3. Directory: this is the element that will define in which folder the files need to be deployed.
  4. Component: this represents the component that needs to be deployed/installed. It can be a file, a registry key, a resource, etc.
  5. Feature: Each product is defined using features, which contains the components that have been declared above.

So, let’s take a look at this simple (but working) example:

<?xml version='1.0'?>

<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>

   <Product Id="5168aa41-582e-4cb2-948f-cf2a8e5dff28" Name="My Addin Package" Language="1033" 

            Version="1.0.0.0" Manufacturer="Thomas Lebrun" UpgradeCode="e22d0f13-3cfa-4644-a466-807a93103c23" >

      <Package Description='My first Windows Installer package'

               Manufacturer="Thomas Lebrun" InstallerVersion='200' Compressed='yes' />

 

      <Directory Id="TARGETDIR" Name="SourceDir">

         <Component Id="MyComponent" Guid="D9247E78-1CB0-4F71-8D28-9F72581A647B" />

      </Directory>

      <Feature Id="MyFeature" Title="My 1st Feature" Level="1">

         <ComponentRef Id="MyComponent" />

      </Feature>

   </Product>

</Wix>

Then, we need to  define which file we want to add to our installer. Indeed, for now, we have specified that a component will be deployed in the folder specify by user but we haven’t set which files will be in that folder. For that, we have to modify the component element to include a File element, which will define:

  1. Its Id
  2. Its name on the disk
  3. The source of the file to get and include in the installer

Again, here is a working example:

<Directory Id="TARGETDIR" Name="SourceDir">

    <Component Id="MyComponent" Guid="D9247E78-1CB0-4F71-8D28-9F72581A647B">

        <File Id="myDll" Name="Sample.dll" Source="Sample.dll" />

    </Component>

</Directory>

Now, if you compile the project, you can go in the bin\Debug (or bin\Release) folder to see your MSI file! Visual Studio handles the call to the executable files (candle and light) that need to be run to create the file!

If you want to create some entries in the registry, it can also be done simply:

<Component Id="MyRegistryKeys" Guid="4D1643FD-A530-4AA0-9D07-BF0469C3D505">

    <RegistryKey Root="HKCU" Key="Software\Microsoft\Office\Excel\Addins\My Addin" Action="createAndRemoveOnUninstall">

        <RegistryValue Type="string" Name="Description" Value="My first Excel addin." />

        <RegistryValue Type="string" Name="FriendlyName" Value="My Addin" />

        <RegistryValue Type="integer" Name="LoadBehavior" Value="3" />

        <RegistryValue Type="string" Name="Manifest" Value="[INSTALLLOCATION]MyAddin.vsto|vstolocal" />

    </RegistryKey>

</Component>

It’s interesting to note that the RegistryKey element has the attribute Action and its value is createAndRemoveOnUninstall, that allows the installer to remove, during the uninstall process, the registry key that has been create.

But, most of time, you need to perform more complex actions when your application is being installed. As an example, it might be necessary for your installer to check if a registry key exists. To do that, you can use the RegistrySearch action which, as you can guess, can be used to perform a search in the registry to locate a particular key.

<Property Id="VSTORUNTIMEREDIST">

    <RegistrySearch Id="VSTORuntimeRedist" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4R" Name="Version" Type="raw" />

</Property>

 

<Property Id="OFFICERUNTIME">

    <RegistrySearch Id="OfficeRuntime" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4" Name="Version" Type="raw" />

</Property>

Here, we use the same action twice to check in the registry if the VSTO 2010 Runtime has been installed (as this one can be installed as part of Office 2010 or as part of Visual Studio 2010, we need to perform 2 checks). Each result of the search is stored in a property and then, it’s possible to use these properties in Conditions element that allow you to display an error message if a specific condition is not satisfied:

<!-- Check if if VSTO 2010 Runtime has been installed by VSTO -->

<Condition Message="The Visual Studio 2010 Tools for Office Runtime is not installed. Please run setup.exe.">

    <![CDATA[Installed OR VSTORUNTIMEREDIST>="10.0.30319"]]>

</Condition>

 

<!-- Check if if VSTO 2010 Runtime has been installed by Office 2010 -->

<Condition Message="The Visual Studio 2010 Tools for Office Runtime is not installed. Please run setup.exe.">

    <![CDATA[Installed OR VSTORUNTIMEREDIST>="10.0.30319" OR OFFICERUNTIME>="10.0.21022"]]>

</Condition>

If you want your installer to look for a specific component, during installation, you can use the ComponentSearch action that will look for the specified product code (identified by a Guid) and let you know if the component is installed or not:

<Property Id="SHAREDPIA">

    <ComponentSearch Id="SharedPia" Guid="64E2917E-AA13-4CA4-BFFE-EA6EDA3AFCB4" />

</Property>

 

<Property Id="EXCELPIA">

    <ComponentSearch Id="ExcelPia" Guid="EA7564AC-C67D-4868-BE5C-26E4FC2223FF" />

</Property>

This time again, we need to use these properties (that allows us to check if the Office Shared PIA and Excel PIA are installed) in a Condition element:

<!-- Search for Office 2010 Shared PIA -->

<Condition Message="A required component for interacting with Excel 2010 is not available. Please run setup.exe.">

    <![CDATA[Installed OR SHAREDPIA]]>

</Condition>

 

<!-- Search for Office 2010 Excel PIA -->

<Condition Message="A required component for interacting with Excel 2010 is not available. Please run setup.exe.">

    <![CDATA[Installed OR EXCELPIA]]>

</Condition>

Now; just compile your project and you’ll get a MSI file that, if you run it, will perform some checks in the registry/components before installing your product. But there is a drawing back using this method. If a prerequisite is missing, you’ll have a MessageBox that will appear and display the message you’ve chosen to show. But users have no way to install the missing components. So we need to find a way to include, in our setup file, the installers of those components.

For that, you can edit the project file of your Wix project, in Visual Studio. Simply right click on your project and choose “Edit Project File”. This will show you the content of the file that is a simple MSBuild file. So, first, inside the Project element, add an ItemGroup element that will define the list of all the prerequisites components that will need to be include in the setup:

<ItemGroup>

    <BootstrapperFile Include="Microsoft.Net.Framework.3.5.SP1">

      <ProductName>.NET Framework 3.5</ProductName>

    </BootstrapperFile>

    <BootstrapperFile Include=".NETFramework,Version=v4.0">

      <ProductName>.NET Framework 4.0</ProductName>

    </BootstrapperFile>

    <BootstrapperFile Include="Microsoft.Windows.Installer.3.1">

      <ProductName>Windows Installer 3.1</ProductName>

    </BootstrapperFile>

    <BootstrapperFile Include="Microsoft.VSTORuntime.4.0">

      <ProductName>VSTO 2010 Runtime</ProductName>

    </BootstrapperFile>

    <BootstrapperFile Include="Microsoft.Office.PIARedist.2007">

      <ProductName>Office 2007 PIA</ProductName>

    </BootstrapperFile>

    <BootstrapperFile Include="Microsoft.Office.PIARedist.2010">

      <ProductName>Office 2010 PIA</ProductName>

    </BootstrapperFile>

</ItemGroup>

Now, we need to tell Wix that these components need to be deployed with our installer. So, at the end of the file, uncomment the target named “After Build” and add the following code:

<GenerateBootstrapper ApplicationFile="$(TargetFileName)"

                      ApplicationName="Intuitive Query Excel Addin"

                      BootstrapperItems="@(BootstrapperFile)" 

                      ComponentsLocation="Relative" 

                      CopyComponents="True" 

                      OutputPath="$(OutputPath)" 

                      Path="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\" />

This code is used to generate a bootstrapper, a setup.exe file that will be used to check the conditions and, if they’re not respected, will launch the setup of the appropriate missing component. The most important parts here are:

  1. BootstrapperItems: that matches to the ItemGroup element containing all the BootstrapperFile. Each element in this group will be defined as a requirement needed to be deployed with your application.
  2. Path: this points to the local path of the prerequisites that should be installed with your installer.

As an example, look at this picture that show all the available package that are on my computer:

SNAGHTML10a2feee

Each of these folders contains components that can be part of the installation of your application (but which need to be installed BEFORE your application).

If you compile your project, you’ll see that a lot of files/folders are generated:

image

The folders contains the prerequisites that are mandatory to install your application. The MSI file is your installer, the one you’ve build with your Wix project. And the setup.exe file is a simple bootstrapper, in charge of detecting the prerequisites, installing them if they are not present and launching the MSI once the system is ready !

Your Wix project is now finished but you can go further and decide to use it to build your application during continuous integration. If you are using Team Foundation Server to perform your builds, this is very easy to do because the Wix project you’ve created in Visual Studio, with the wixproj extension, is an MSBuild file. So, during your build, you can just run the MSBuild.exe application, giving it your Wix project:

image

As you’ve seen during this article, Wix files are only XML files so it might not be much fun to modify them in Visual Studio, even if we do get Intellisense. So you can take a look at the tool named WixEdit, that allow you to edit Wix files (with extension wxs) through a graphical interface:

SNAGHTML1464332b

Finally, here is a little tip if you already have a MSI file and want to get the Wix file corresponding to it. You can use the command-line tool Dark.exe’ (located in C:\Program Files\Windows Installer XML v3.6\bin or C:\Program Files (x86)\Windows Installer XML v3.6\bin) to decompile the MSI file.
Be careful, the file might be a quite big and hard to understand but you should be able to get a lot of useful information from it.

 

I hope this article helped you to better understand Wix and how to use it to build your own installers. I’ll try to publish more articles on Wix as soon as possible.

 

Happy coding!

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

One Response



Add Comment Register



Leave a Reply