Getting started with customizing WiX bootstrapper UI

I wrote this as a guide for people like me who are floundering trying to distill the myriad bits of documentation, forum posts, and blog posts down to the essential bits of "How do I display some different text in my WiX bootstrapper application?"

In particular, I'm going to talk about displaying version info on the first page of the bootstrapper UI, something like this:

custom bootstrapper UI with version info

Here are the caveats: This worked for me using WiX 3.8; I don't know whether this will apply to other versions. Also, I'm currently doing an English-language-only installer; I suspect that what I'm doing is compatible with multi-language installers, but I've not tested it in that situation. Also, there may be better, easier, more WiX appropriate ways to do this. Like I said, the documentation and other information on the web is confusing at best. So this is what I put together. It's a bit of a kludge - I took the "Display an RTF EULA and an 'Accept' checkbox" default UI and modified it to my purposes. I'm actually not using most parts of the UI, but I've left them in so I can turn them on in the future (I'm likely to need that EULA ability eventually).

In order to get a custom string on the screen, you're going to need to customize two different parts of the interface. The first is the XML theme for the bootstrapper. This file defines most of the UI (the window, the pages in the installer, the fonts, etc.). Rather than write my own UI from scratch, I cloned the WiX source code from git@github.com:wixtoolset/wix3.git and dug down to one of their default UI definition files: src\ext\BalExtension\wixstdba\Resources\RtfTheme.xml. This is the default definition for a UI which displays a rich-text-format EULA on the first page.

I took RtfTheme.xml, renamed it thm.xml, and dropped it into my project next to Bundle.wxs. In order to display the version number on the main installer page, I modify the <Page Name="Install"> element by adding a simple text field:

    <Text X="11" Y="-73" Width="246" Height="17" FontId="3">#(loc.InstallVersion)</Text>

This new element is pretty self-explanatory - some positioning and sizing information, and a reference to a string which is defined elsewhere (in a .wxl file which we will add in a moment).

The next part was the bit which had me stumped for quite a while. You'll want to add the .wxl file from src\ext\BalExtension\wixstdba\Resources\RtfTheme.wxl to your project. Based on some docs and forum posts, I spent a while trying to get this to work with the .wxl file in the same folder as the .xml theme file (since this was a single-language installer). After some fiddling, it turned out that I needed to put the .wxl (which I creatively named thm.wxl) into a language-specific folder. So in my bootstrapper project I created a folder called 1033 (English-US) next to Bundle.wxs and added the thm.wxl file to it. In the end, the files in the BootStrapper project look like this:

    /1033
        /thm.wxl
    /Bundle.wxs
    /thm.xml

The .wxl file contains all of the strings used in the bootstrapper UI; if you're looking to change window captions, buttons captions, labels, or anything else this is what you're looking for. By default the InstallVersion string is bound to the bundle version, which will also be the version of your application if you've set things up like I did in the article about coordinating app and installer versions.

Finally, I modified Bundle.wxs to use my customized theme:


<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
     xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">

...

    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
      <bal:WixStandardBootstrapperApplication LicenseUrl="" ThemeFile="thm.xml"/>
      <Payload Name="1033\thm.wxl" SourceFile="1033\thm.wxl" />
    </BootstrapperApplicationRef>

...

</Wix>

(Notice the BalExtension namespace we're adding.) With all that in place, I now had a bootstrapper which displayed the version number on the first installation page. I also had everything in place to customize the rest of the bootstrapper UI, should that ever become a requirement, and the pieces in place to add localized strings for other languages if we need, for example, a Spanish-language installer.