Updated instructions for building patches using the new WiX v3.0 patch building system

My new team is using WiX v3.0 to create the MSI-based setups for the upcoming XNA Game Studio 2.0 product.  One of the readiness activities we're working on prior to shipping is testing the process of building and installing patches for these MSIs.

Our primary setup developer started out with this testing process by investigating the patching features in WiX v3.0.  She read through the introductory information in Peter Marcu's blog.  In particular, she attempted to use the sample patch build instructions in this blog post to create an MSP for one of our MSIs.  While doing this, she found that our build process was not creating or archiving .wixout files, which are required to build patches using these instructions.

Fortunately, a couple of things have changed in WiX v3.0 since the time that Peter wrote that blog post.  The first was a code change that Peter added in early August to WiX v3.0 that makes the WiX build process produce artifacts needed for patching by default.  In other words, you have to pass command line switches to turn off the creation of the files instead of to turn it on, which means that if you don't know about the need to create these artifacts at the time that you build your original product, you won't have to go back and rebuild your baseline product before you can build an upgrade layout and a patch.  You can see this change in recent WiX v3.0 builds (3.0.3210.0 or higher) by performing a default compile and link and observing the .wixpdb files that are created.  You can also see the -spdb switch that is now available in light.exe to suppress the creation of the .wixpdb files.

The second change in WiX 3.0 is some greatly enhanced patch building documentation that was added to wix.chm by Heath Stewart (he references these docs in this blog post).  If you have a recent build of WiX v3.0 (build 3.0.3210.0 or higher), you can see the new patching documentation in wix.chm by looking under WiX Help | Authoring | Patch Building in the table of contents.

Since the contents of wix.chm are not searchable via Web search engines, I am going to transcribe an updated set of instructions from one of the help topics that Heath wrote so that people using more recent builds of WiX v3.0 will hopefully find and use these instructions instead of the ones that Peter originally posted when getting started building patches using WiX v3.0.

Patch Building Using Purely WiX

A patch can now be created purely in WiX using new tools, Torch.exe and Pyro.exe. This also eliminates the need to perform administrative installs or even bind the upgrade product which, for large products, can be exhaustive.  Creating a patch consists of 3 steps:

  • Setting up the patch sample
  • Building the patch sample
  • Verify the patch sample

Setting Up the Patch Sample

A sample product is created which puts different resources into fragments. The purpose of putting resources into separate fragments is so that the resources in each fragment can be filtered out of a patch. You might filter some resources out of a patch if you only want to limit the patch to update only parts of your product or products.

1. Create a directory that will contain the sample

Create a directory from which you plan on running the sample. This will be the sample root.

md C:\sample

2. Create two subdirectories

Under the sample root create two subdirectories called "1.0" and "1.1".

md C:\sample\1.0
md C:\sample\1.1

3. Create a text file called Sample.txt for 1.0

Create a text file in the "1.0" directory called Sample.txt and put some text in it telling you that it is the 1.0 version of the file.

echo This is version 1.0 > C:\sample\1.0\Sample.txt

4. Create a text file called Sample.txt for 1.1

Create a text file in the "1.1" directory called Sample.txt and put some text in it telling you that it is the 1.1 version of the file.

echo This is version 1.1 > C:\sample\1.1\Sample.txt

5. Create your product authoring in the sample root folder

Create your product authoring in the sample root folder called Product.wxs with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="https://schemas.microsoft.com/wix/2006/wi">
    <Product Id="48C49ACE-90CF-4161-9C6E-9162115A54DD"
        Name="WiX Patch Example Product"
        Language="1033"
        Version="1.0.0"
        Manufacturer="Dynamo Corporation"
        UpgradeCode="48C49ACE-90CF-4161-9C6E-9162115A54DD">
        <Package Description="Installs a file that will be patched."
            Comments="This Product does not install any executables"
            InstallerVersion="200"
            Compressed="yes" />
        <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
        <FeatureRef Id="SampleProductFeature"/>
    </Product>
    <Fragment>
        <Feature Id="SampleProductFeature" Title="Sample Product Feature" Level="1">
            <ComponentRef Id="SampleComponent" />
        </Feature>
    </Fragment>
    <Fragment>
        <DirectoryRef Id="SampleProductFolder">
            <Component Id="SampleComponent" Guid="{C28843DA-EF08-41CC-BA75-D2B99D8A1983}" DiskId="1">
                <File Id="SampleFile" Name="Sample.txt" Source=".\$(var.Version)\Sample.txt" />
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder" Name="PFiles">
                <Directory Id="SampleProductFolder" Name="Patch Sample Directory">
                </Directory>
            </Directory>
        </Directory>
    </Fragment>
</Wix>

6. Create your patch authoring in the sample root

Create your patch authoring in the sample root called Patch.wxs with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="https://schemas.microsoft.com/wix/2006/wi">
    <Patch
        AllowRemoval="yes"
        Manufacturer="Dynamo Corp"
        MoreInfoURL="https://www.dynamocorp.com/"
        DisplayName="Sample Patch"
        Description="Small Update Patch"
        Classification="Update"
        >
        <Media Id="5000" Cabinet="RTM.cab">
            <PatchBaseline Id="RTM"/>
        </Media>
        <PatchFamilyRef Id="SamplePatchFamily"/>
    </Patch>
    <Fragment>   
        <PatchFamily Id='SamplePatchFamily' Version='1.0.0.0' Supersede='yes'>
            <ComponentRef Id="SampleComponent"/>
        </PatchFamily>
    </Fragment>
</Wix>

Building the Patch Sample

Open a command prompt and make sure that the following WiX tools are in your PATH.

  • Candle.exe
  • Light.exe
  • Torch.exe
  • Pyro.exe

Your WiX toolset version should be at least 3.0.3210.0

1. Build the target layout

While only the wixpdb is needed, the target product layout is created to test installing the patch which requires the product is also installed before or along with the patch.

cd C:\sample
candle.exe -dVersion=1.0 product.wxs
light.exe product.wixobj -out 1.0\product.msi

2. Build the upgrade layout

candle.exe -dVersion=1.1 product.wxs
light.exe product.wixobj -out 1.1\product.msi

3. Create the transform between your products

torch.exe -p -xi 1.0\product.wixpdb 1.1\product.wixpdb -out patch\diff.wixmst

4. Build the patch

The patch.wxs file is compiled and linked similar to a product, but then processed along with any number of transforms that you want contained in the patch. That produces an MSP file that targets any of the products from which transforms were created that contain at least some small change after filtering.

candle.exe patch.wxs
light.exe patch.wixobj -out patch\patch.wixmsp
pyro.exe patch\patch.wixmsp -out patch\patch.msp -t RTM patch\diff.wixmst

Verify the Patch

To verify that the patch works, install the product and then the patch.

1. Install the 1.0 product

msiexec.exe /i 1.0\product.msi /l*vx install.log

2. Verify version 1.0

Go to "Program Files\Patch Sample Directory" and open Sample.txt. Verify that this is the 1.0 version. Close Sample.txt.

3. Install the patch

msiexec.exe /p patch\patch.msp /l*vx patch.log

4. Verify version 1.1

Go to "Program Files\Patch Sample Directory" and open Sample.txt. Verify that this is now the 1.1 version. Close Sample.txt.

5. Uninstall the patch

On Windows XP Service Pack 2 and Windows Server 2003, go to "Add/Remove Programs" in the Control Panel and make sure that Show Updates is checked. On Windows Vista and newer, go to "Programs" then "View installed updates" in the Control panel. Select "Sample Patch" from under "WiX Patch Example Product" and click the Uninstall button.

Go to "Program files\Patch Sample Directory" and open Sample.txt. Verify that this is again the 1.0 version. Close Sample.txt.

6. Uninstall the product

On Windows XP Service Pack 2 and Windows Server 2003, go to "Add/Remove Programs" in the Control Panel. On Windows Vista and newer, go to "Programs" then "Uninstall a program" in the Control Panel. Select "WiX Patch Example Product" and click the Uninstall button.

Restrictions

In addition to restrictions about what can be in a patch for it to correctly install and uninstall, building patches using purely WiX has additional restrictions to help ensure that your patch works correctly.

1. Patch families can only ever grow

Patch families are used to filter resources that should end up in a patch. Once the patch is created, these patch families dictate which patches are superseded. If a resource is removed from a patch family in a newer patch when that resource is contained in an older patch with the same patch family, when the older patch is superseded that resource will be regressed back to its previous state before the older patch was even installed.

Note that in order for one patch to supersede any other patches, all patch families must be superseded. A single patch family is referenced in the example above for simplicity.

2. Certain elements cannot be added to uninstallable patches

There are certain elements referenced in restrictions that cannot be added or modified if the patch is to be uninstallable. If a Patch/@AllowRemoval is set to "yes" and any of these elements are added or modified, Pyro.exe will return an error. These elements compile into tables that Windows Installer restricts in patches, so WiX informs and prevents you from creating an uninstallable patch that you want to be uninstallable.