WiX Tutorial (1/7)

Introduction

The WiX toolkit is an open source toolkit to create Windows Installer [1] packages (MSI files).

The toolkit can be downloaded from the http://wixtoolset.org/releases/ page.

Build Process

To create a package with WiX the first step is to write a WiX source file (.wxs) that describes the package. WiX source files are XML files and can be created manually as we're going to show shortly. The Candle.exe executable is used to compile the WiX source files into intermediate object files (.wixobj). The Light.exe executable is then used to create the MSI file from the intermediate object files. This process is illustrated on Figure 1.

The WiX Build Process
Figure 1: The WiX Build Process

GUIDs

Several of the elements of an installer have a unique identifier. These identifiers are GUIDs [2], This ensures that the system can install and manage packages from different origins without any risk of conflicts. Various ways of getting GUIDs are described at Pragmateek: 4 ways to generate a GUID [3].

In some cases WiX can generate GUIDs automatically for you if you don't specify one explicitly. I don't actually recommend this as in a lot of cases this will not produce the desired result. The exception to that rule is the <Package> element mentioned later on this page where it makes sense to let WiX generate the GUID.

The examples on these pages are working examples and therefore use genuine GUIDs. When creating your own packages make sure that you replace all GUIDs with your own. Copy/paste isn't your friend when working with GUIDs.

A Simple Installer

Let's start with a simple example. We want to build an MSI file that will install a single file in a directory in the "Program Files" folder. Here is the WiX source file we have written to achieve this. The full example is available from our Codeplex repository at WiX/Basics/SingleFileInstallation1.

File: SingleFileInstallation1.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="13BA1A0D-B457-402C-94C0-37C059D68D1A" Name="SingleFileInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software"
        UpgradeCode="24C630F0-4BCE-4050-A940-30DDF7D0BBE7">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
        <MediaTemplate EmbedCab="yes" />

        <Feature Id="MainProduct" Title="Single File Installation 1" Level="1">
            <ComponentRef Id="HelloWorldComponent" />
        </Feature>

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="NeedfulSoftwareDir" Name="Needful Software">
                    <Directory Id="SingleFileInstallation1Dir" Name="Single File Installation 1">

                        <Component Id="HelloWorldComponent" Guid="D84FC5FF-58A0-40BF-92CE-5FD447125670">
                            <File Id="HelloWorldFile" Source="HelloWorld.txt" KeyPath="yes" />
                        </Component>

                    </Directory>
                </Directory>
            </Directory>
        </Directory>

    </Product>

</Wix>

This MSI files uses a file called HelloWorld.txt that is put in the same directory as SingleFileInstallation1.wxs, its contents don't matter for this example. We just want to install it somewhere and check it has been installed.

We compile the MSI using the following commands:

Command line
C:\WiX\Examples\SingleFileInstallation1>candle.exe SingleFileInstallation1.wxs
Windows Installer XML Toolset Compiler version 3.8.1128.0
Copyright (c) Outercurve Foundation. All rights reserved.

SingleFileInstallation1.wxs

C:\WiX\Examples\SingleFileInstallation1>light.exe SingleFileInstallation1.wixobj
Windows Installer XML Toolset Linker version 3.8.1128.0
Copyright (c) Outercurve Foundation. All rights reserved.


C:\WiX\Examples\SingleFileInstallation1>

This will create an MSI file called SingleFileInstallation1.msi. We can install this file by simply double-clicking it. After install the HelloWorld.txt file should have been installed in C:\Program Files (x86)\Needful Software\Single File Installation 1. The package can be uninstalled from the Control Panel or by right-clicking SingleFileInstallation1.msi and selecting the uninstall option.

Alternatively you can install and remove the package from the command line with the following commands:

Command line
C:\WiX\Examples\SingleFileInstallation1>msiexec /i SingleFileInstallation1.msi

C:\WiX\Examples\SingleFileInstallation1>msiexec /x SingleFileInstallation1.msi

C:\WiX\Examples\SingleFileInstallation1>

Note that our installer doesn't come with its own UI, the dialogs displayed when installing or uninstalling are the built-in dialogs. In the next tutorial we will show how to add a UI to the installer to produce a more pleasant and flexible installation experience.

Since our SingleFileInstallation1 installer doesn't need any user interaction we can install and remove it silently by using the /qn option as shown below.

Command line
C:\WiX\Examples\SingleFileInstallation1>msiexec /qn /i SingleFileInstallation1.msi

C:\WiX\Examples\SingleFileInstallation1>msiexec /qn /x SingleFileInstallation1.msi

C:\WiX\Examples\SingleFileInstallation1>

Source File Format

Let's now look at the SingleFileInstallation1.wxs in more details. We will build the previous example step by step.

This tutorial shows you how to create an MSI file with WiX but doesn't discuss the MSI file format in details. If you are interested in the internal structure of the created MSI file, the Windows Installer tutorial takes a look inside the created MSI file.

The Wix root element

As we mentioned at the start of this tutorial, WiX source files are XML file. The root element of the XML document is <Wix> and the schema is http://schemas.microsoft.com/wix/2006/wi. Documentation for the schema can be found at WiX Toolset: Wix Schema [4]. As a consequence a Wix source file follows the structure below:

Structure of a WiX source file: The Wix Root Element
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    ... Contents ...

</Wix>

The Product element

To create an MSI a single <Product> element must be defined inside the <Wix> root element. The <Product> element's attributes provide information about the product that is being installed by the MSI file.

The Name, Version and Manufacturer attributes are self-explanatory.

The Id attribute is a GUID and is the ProductCode of the product. There are some guidelines to follow about whether the ProductCode should be changed or not when producing new releases of the product. We explain them in more details here.

The UpgradeCode is a GUID that identifies the product across all releases. While the ProductCode may change the UpgradeCode should never change and can be used to identify any release of the product. We explain how to use the UpgradeCode here.

Structure of a WiX source file: The Product Element
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="13BA1A0D-B457-402C-94C0-37C059D68D1A" Name="SingleFileInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software" UpgradeCode="24C630F0-4BCE-4050-A940-30DDF7D0BBE7">

        ... Contents ...
        
    </Product>

</Wix>

The Package element

Inside the <Product> element a few child elements are needed. The first one is a <Package> element that provides information about the MSI. The <Product> element gives information about the thing being installed while the <Package> element gives information about the MSI file itself.

The <Package> element has an Id attribute but this is a case where leaving it empty and letting WiX generate one automatically is a good approach. This is because this is the GUID of the MSI file itself. If you change anything in the file then you have a different file and therefore you should give it a new GUID so you would end up changing this GUID all the time anyway.

Structure of a WiX source file: The Package Element
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="13BA1A0D-B457-402C-94C0-37C059D68D1A" Name="SingleFileInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software" UpgradeCode="24C630F0-4BCE-4050-A940-30DDF7D0BBE7">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

        ... Contents ...
        
    </Product>

</Wix>

The MediaTemplate element

The <MediaTemplate> is used to describe how the installer is stored on physical disks. Nowadays it is common to download the installer from the Internet so this element can be very simple as shown below. If the installer needs to span several physical disks then this element can be used to describe that structure.

Structure of a WiX source file: The MediaTemplate Element
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="13BA1A0D-B457-402C-94C0-37C059D68D1A" Name="SingleFileInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software" UpgradeCode="24C630F0-4BCE-4050-A940-30DDF7D0BBE7">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
        <MediaTemplate EmbedCab="yes" />

        ... Contents ...

    </Product>

</Wix>

The Feature element

In a Windows Installer, the items to be installed and actions to be performed are grouped into features. A simple installer will only have one feature containing all the items and actions to be installed. However if for instance the application has a main product and also documentation, it is possible to make installation of the documentation optional by grouping the items of the main product in one feature and the documentation files in another. The user can then choose which features should be installed.

The files and actions themselves are not used directly by the features, they are contained in components which are then included by features.

For our simple example we have one feature which contains one component as shown below.

Structure of a WiX source file: The Feature Element
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="13BA1A0D-B457-402C-94C0-37C059D68D1A" Name="SingleFileInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software" UpgradeCode="24C630F0-4BCE-4050-A940-30DDF7D0BBE7">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
        <MediaTemplate EmbedCab="yes" />

        <Feature Id="MainProduct" Title="Single File Installation 1" Level="1">
            <ComponentRef Id="HelloWorldComponent" />
        </Feature>

        ... Contents ...

    </Product>

</Wix>

Installing Two Files

Installing two files to the same directory isn't more difficult than installing one. We modify the previous example to install an additional file, Goodbye.txt, in the same directory as HelloWorld.txt. This can be done by adding another <Component> element inside the appropriate <Directory> element and another <ComponentRef> element inside the <Feature> element. This is shown below with the changes highlighted in red. Note that we also changed the package name and all GUIDs as this is a new installer for a supposedly different product but didn't highlight those changes as they are not relevant.

It is actually possible to put more than one <File> element into a <Component> element but this has some unexpected effects during a repair operation. So you should always put each file into a component of its own unless you have some special requirements.

The full example is available from our Codeplex repository at WiX/Basics/TwoFilesInstallation1.

File: TwoFilesInstallation1.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

    <Product Id="8A30D017-A143-47E5-ADF6-6D122F1D11C3" Name="TwoFilesInstallation1" Language="1033" 
        Version="1.0.0.0" Manufacturer="Needful Software" UpgradeCode="5F6BB609-01DA-4421-85FA-0FF0FC0F8A77">

        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
        <MediaTemplate EmbedCab="yes" />

        <Feature Id="MainProduct" Title="Two Files Installation 1" Level="1">
            <ComponentRef Id="HelloWorldComponent" />
            <ComponentRef Id="GoodbyeComponent" />
        </Feature>

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="NeedfulSoftwareDir" Name="Needful Software">
                    <Directory Id="TwoFilesInstallation1Dir" Name="Two Files Installation 1">

                        <Component Id="HelloWorldComponent" Guid="095D68A7-FEC1-410D-BB47-0BCD05AB2F50">
                            <File Id="HelloWorldFile" Source="HelloWorld.txt" KeyPath="yes" />
                        </Component>

                        <Component Id="GoodbyeComponent" Guid="D3E59C34-F4F3-4EA9-A485-10D0D5AC1512">
                            <File Id="GoodbyeFile" Source="Goodbye.txt" KeyPath="yes" />
                        </Component>
    
                    </Directory>
                </Directory>
            </Directory>
        </Directory>

    </Product>

</Wix>

References

  1. Wikipedia: Windows Installer
  2. Wikipedia: Globally unique identifier
  3. Pragmateek: 4 ways to generate a GUID
  4. WiX Toolset: Wix Schema

Further Reading

  1. WiX Tutorial: Introduction to the Windows Installer XML Toolset
  2. Alex Shevchuk's Blog: From MSI to WiX

blog comments powered by Disqus

Copyright(c) 2006-2017 Xavier Leclercq | Privacy policy

Home
Contact Us
Search