Windows Installer XML (WiX): Adding a User Interface

Exclusive offer: get 50% off this eBook here
WiX: A Developer's Guide to Windows Installer XML

WiX: A Developer's Guide to Windows Installer XML — Save 50%

Create a hassle-free installer for your Windows software using WiX

$29.99    $15.00
by Nick Ramirez | October 2010 | Open Source

The WiX toolset ships with several User Interface wizards that are ready to use out of the box. We'll briefly discuss each of the available sets and then move on to learning how to create your own from scratch. In this article by Nick Ramirez, author of the book WiX: A Developer's Guide to Windows Installer XML, you'll learn about:

  • Adding dialogs into the InstallUISequence
  • Linking one dialog to another to form a complete wizard
  • Getting basic text and window styling working
  • Including necessary dialogs like those needed to display errors
        Read more about this book      

(For more resources on WiX, see here.)

WiX standard dialog sets

The wizards that come prebuilt with WiX won't fit every need, but they're a good place to get your feet wet. To add any one of them, you first have to add a project reference to WixUIExtension.dll, which can be found in the bin directory of your WiX program files.

Adding this reference is sort of like adding a new source file. This one contains dialogs. To use one, you'll need to use a UIRef element to pull the dialog into the scope of your project. For example, this line, anywhere inside the Product element, will add the "Minimal" wizard to your installer:

<UIRef Id="WixUI_Minimal" />

It's definitely minimal, containing just one screen.

It gives you a license agreement, which you can change by adding a WixVariable element with an Id of WixUILicenseRtf and a Value attribute that points to a Rich Text Format (.rtf) file containing your new license agreement:

<WixVariable Id="WixUILicenseRtf"
Value="newLicense.rtf" />

You can also override the background image (red wheel on the left, white box on the right) by setting another WixVariable called WixUIDialogBmp to a new image. The dimensions used are 493x312. The other available wizards offer more and we'll cover them in the following sections.

WixUI_Advanced

The "Advanced" dialog set offers more: It has a screen that lets the user choose to install for just the current user or for all users, another where the end user can change the folder that files are installed to and a screen with a feature tree where features can be turned on or off. As in the following screenshot:

You'll need to change your UIRef element to use WixUI_Advanced. This can be done by adding the following line:

<UIRef Id="WixUI_Advanced" />

You'll also have to make sure that your install directory has an Id of APPLICATIONFOLDER, as in this example:

<Directory Id="TARGETDIR"
Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONFOLDER"
Name="My Program" />
</Directory>
</Directory>

Next, set two properties: ApplicationFolderName and WixAppFolder. The first sets the name of the install directory as it will be displayed in the UI. The second sets whether this install should default to being per user or per machine. It can be either WixPerMachineFolder or WixPerUserFolder.

<Property Id="ApplicationFolderName"
Value="My Program" />
<Property Id="WixAppFolder"
Value="WixPerMachineFolder" />

This dialog uses a bitmap that the Minimal installer doesn't: the white banner at the top. You can replace it with your own image by setting the WixUIBannerBmp variable. Its dimensions are 493x58. It would look something like this:

<WixVariable Id="WixUIBannerBmp"
Value="myBanner.bmp" />

WixUI_FeatureTree

The WixUI_FeatureTree wizard shows a feature tree like the Advanced wizard, but it doesn't have a dialog that lets the user change the install path. To use it, you only need to set the UIRef to WixUI_FeatureTree, like so:

<UIRef Id="WixUI_FeatureTree" />

This would produce a window that would allow you to choose features as show in the following screenshot:

Notice that in the image, the Browse button is disabled. If any of your Feature elements have the ConfigurableDirectory attribute set to the Id of a Directory element, then this button will allow you to change where that feature is installed to. The Directory element's Id must be all uppercase.

WixUI_InstallDir

WixUI_InstallDir shows a dialog where the user can change the installation path. Change the UIRef to WixUI_InstallDir. Like so:

<UIRef Id="WixUI_InstallDir" />

Here, the user can chose the installation path. This is seen in the following screenshot:

You'll have to set a property called WIXUI_INSTALLDIR to the Id you gave your install directory. So, if your directory structure used INSTALLLDIR for the Id of the main install folder, use that as the value of the property.

<Directory Id="TARGETDIR"
Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR"
Name="My Program" />
</Directory>
</Directory>

<Property Id="WIXUI_INSTALLDIR"
Value="INSTALLDIR" />

WixUI_Mondo

The WixUI_Mondo wizard gives the user the option of installing a "Typical", "Complete" or "Custom" install. Typical sets the INSTALLLEVEL property to 3 while Complete sets it to 1000. You can set the Level attribute of your Feature elements accordingly to include them in one group or the other. Selecting a Custom install will display a feature tree dialog where the user can choose exactly what they want. To use this wizard, change your UIRef element to WixUI_Mondo.

<UIRef Id="WixUI_Mondo" />

This would result in a window like the following:

WiX: A Developer's Guide to Windows Installer XML Create a hassle-free installer for your Windows software using WiX
Published: October 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on WiX, see here.)

Customizing a standard dialog set

Each of the dialog sets shown can be customized by adding screens, removing some, or changing the look and text. Usually, this means downloading the WiX source code and changing the markup in the dialogs. You can find them under the src\ext\UIExtension\wixlib folder of the source code.

The general procedure is to copy the .wxs file that has the name of the wizard, such as WixUI_Minimal.wxs, to your project with a different name. Then, using the other .wxs files in that folder as a reference, add or remove DialogRef elements to add or remove dialogs. DialogRefs are the references to the dialogs in the other files. Files such as WixUI_Minimal.wxs just tie them all together into a wizard. For example, here's part of what you'd find in the Minimal wizard's main source file:

<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<DialogRef Id="WelcomeEulaDlg" />

Here, you could remove the welcome dialog from the wizard by removing the WelcomeEulaDlg line. The Minimal wizard is pretty small to begin with so you're probably better off customizing a set like Mondo.

Scanning through the rest of the file, you'll find that it uses Publish elements to define where the Next button on each dialog takes you to. You can, in your custom file, change that. Here's what you'd find in WixUI_Mondo.wxs:

<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="LicenseAgreementDlg">1</Publish>

<Publish Dialog="LicenseAgreementDlg"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg">1</Publish>

<Publish Dialog="LicenseAgreementDlg"
Control="Next"
Event="NewDialog"
Value="SetupTypeDlg"
Order="2">LicenseAccepted = "1"</Publish>

This is all unfamiliar still and we'll go over the Publish element in more detail when we talk about creating our own dialogs. For now, notice that we pair Dialog and Control attributes to find a particular UI control, such as a button, on a specific dialog. The first Publish element, for example, finds the Next button on the WelcomeDlg dialog. Use the Event attribute to add an event such as NewDialog to the button.

Here, we're saying we want the Next button to fire the NewDialog event with a Value of LicenseAgreementDlg. This means that when the button is clicked, WelcomeDlg will be replaced with LicenseAgreementDlg. You can customize any control on any dialog from here, usually to change where Next and Back buttons take you. This allows you to insert new dialogs or skip one you don't want.

Here's an example that inserts a custom dialog between the WelcomeDlg and the LicenseAgreementDlg. Add this to the CustomWixUI_Mondo.wxs file:

<Publish Dialog="WelcomeDlg"
Control="Next"
Event="NewDialog"
Value="MyDialog">1</Publish>

<Publish Dialog="MyDialog"
Control="Back"
Event="NewDialog"
Value="WelcomeDlg">1</Publish>

<Publish Dialog="MyDialog"
Control="Next"
Event="NewDialog"
Value="LicenseAgreementDlg">1</Publish>

<Publish Dialog="LicenseAgreementDlg"
Control="Back"
Event="NewDialog"
Value="MyDialog">1</Publish>

Remember, you'd need to get the original WixUI_Mondo.wxs file from the WiX source and rename it to something like CustomWixUI_Mondo.wxs before adding it to your project. You'll then reference the custom file with a UIRef. We'll explain more about referencing dialog sets when we discuss creating dialogs from scratch.

Creating your own dialogs

In this section, we'll discard the premade dialogs and create our own. This should give you a much deeper understanding of how things work.

ICE20 errors

For these first exercises, you'll have to ignore some of WiX's warnings. Go to the Properties page for the project, select Tools Settings and add a rule to ignore the validation test ICE20. This test checks that you've added FilesInUse, Error, FatalError, UserExit, and Exit dialogs. That's a lot to start out with so for now, just ignore those rules.

What are these dialogs? They are all windows that serve the purpose of showing an error or a message explaining that the installation has completed successfully. They show up automatically when they're needed. Later in the article, I'll show how you can create these dialogs to meet the requirements of ICE20.

Adding dialog files

Let's remove the reference to the WixUIExtension.dll and the UIRef that points to a standard dialog. We'll be creating everything ourselves now to get the best working knowledge. Each dialog window that you create should be placed into its own WiX source file (.wxs). In Visual Studio, you can right-click on your project and select Add | New Item | WiX File.

This will create an XML file containing a Wix root element and a Fragment element. Fragments can be used to split your code into separate files and as such can be used for many different purposes. To create a dialog out of one, you'll need to add two more elements: UI and Dialog. In this example, I've added a UI element and given it an Id of InstallDlg_UI. Inside that, I've nested a Dialog element, which I've called InstallDlg. The InstallDlg.wxs file should look like this:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="InstallDlg_UI">
<Dialog Id="InstallDlg">
<!--Controls like buttons and text go here-->
</Dialog>
</UI>
</Fragment>
</Wix>

This is the basic structure that you'll use for each new dialog. The first dialog that you create can serve as the entry point for the others. If, for example, we created a second dialog called SecondDlg, we could set it up in the same way. On additional dialogs, you can omit the UI element's Id attribute, but be sure to change the Dialog element's Id to something new. Use the following snippet to build your SecondDlg.wxs file:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="SecondDlg">
<!--Controls like buttons and text go here-->
</Dialog>
</UI>
</Fragment>
</Wix>

Then, to reference SecondDlg in our first dialog, add a DialogRef element to out InstallDlg.wxs file:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="InstallDlg_UI">
<DialogRef Id="SecondDlg"/>

<Dialog Id="InstallDlg">
</Dialog>
</UI>
</Fragment>
</Wix>

To add both dialogs to our project, use a UIRef in your main source file. Its Id should match the Id you gave to your UI element in InstallDlg. Add this line to Product.wxs:

<UIRef Id="InstallDlg_UI"/>

Scheduling dialogs

For now, we only need to schedule one of our dialogs in the UI sequence. To do that, place a Show element inside an InstallUISequence element with a Dialog attribute set to the Id of InstallDlg file's Dialog element. Then add a Before attribute and schedule it before ExecuteAction. The following snippet shows this:

<InstallUISequence>
<Show Dialog="InstallDlg"
Before="ExecuteAction" />
</InstallUISequence>

Now, when the installer is launched our first dialog will be shown. To get from our first dialog to our second one, we'll add a Next button that takes us there. Basically, you'll add a Control element of Type = "PushButton" inside the InstallDlg file's Dialog element. It will, in turn, contain another element called Publish that closes the current dialog and opens the second. The InstallDlg.wxs file will contain this code:

<Dialog ...>
<Control Id="Next"
Type="PushButton"
X="245"
Y="243"
Width="100"
Height="17">
<Publish Event="NewDialog"
Value="SecondDlg" />
</Control>
</Dialog>

This technique can be used to navigate from one dialog to another, or even to go back via Back buttons. You only need to change the value of the Publish element's Value attribute to the Id of a different Dialog. We could add a Back button on our SecondDlg file that takes us back to InstallDlg:

<Dialog ...>
<Control Id="Back"
Type="PushButton"
X="180"
Y="243"
Width="100"
Height="17">
<Publish Event="NewDialog"
Value="InstallDlg" />
</Control>
</Dialog>

Of course, you'd also need to change the Id of the Control and change its X and Y attributes, otherwise all of your buttons would sit on top of one another and have the same key in the MSI's Control table. Here's an image of a dialog that has a Back and Next button:

Dialog element

Our InstallDlg won't work properly yet. We still need to add more attributes to the Dialog element to set its size, title, and whether or not it can be minimized:

<Dialog Id="InstallDlg"
Width="370"
Height="270"
Title="Amazing Software"
NoMinimize="no">

You can set the Width and Height larger or smaller, but these are the dimensions used by the WiX dialog sets. Together, these define the size of the window. The Title attribute sets the text that will be displayed at the top of the window. Setting NoMinimize to no means that the user will be able to minimize the dialog. This is the default so specifying it isn't strictly necessary. There's one other attribute that you're likely to use early on and that's Modeless, which can be set to yes. This will make the dialog not wait for user input and is often used for progress bar dialogs. We'll cover it later on in the article.

Adding TextStyle elements

Our dialog isn't useable yet. It needs at least one TextStyle element to set the default font for the text on the window. You'll only need to do this for the first dialog you create. The other dialogs can reuse the styles you set there. A TextStyle element uses the FaceName, Size, Bold, Italic, and Underline attributes to set a font. The following example creates a vanilla 8pt Tahoma font to be used as our default:

<TextStyle Id="Tahoma_Regular"
FaceName="Tahoma"
Size="8" />
<Property Id="DefaultUIFont"
Value="Tahoma_Regular" />

Since this will be our default font, we have to add a Property with an Id set to DefaultUIFont and a Value set to the Id of our TextStyle element. These will go inside our UI element as siblings to our Dialog element. You can add more TextStyle elements for titles, fine print and so on.

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="InstallDlg_UI">
<TextStyle Id="Tahoma_Regular"
FaceName="Tahoma"
Size="8" />
<Property Id="DefaultUIFont"
Value="Tahoma_Regular" />

<TextStyle Id="Tahoma_Bold"
FaceName="Tahoma"
Size="8"
Bold="yes" />
<TextStyle Id="Tahoma_Italic"
FaceName="Tahoma"
Size="8"
Italic="yes" />
<TextStyle Id="Tahoma_Title"
FaceName="Tahoma"
Size="12"
Underline="yes" />

<Dialog Id="InstallDlg"
Width="370"
Height="270"
Title="Amazing Software"
NoMinimize="no">
</Dialog>
</UI>
</Fragment>
</Wix>

You can use these styles on, for example, a Control of Type = "Text", which displays a label, by adding the TextStyle element's Id in curly brackets to the Control element's Text attribute. Prefix the Id with a backslash as shown:

<Control Id="myText"
Type="Text"
X="10" Y="10"
Width="200"
Height="17"
Text="{\Tahoma_Bold}Here is some text" />

The following table lists the possible attributes for your TextStyle elements:

Attribute

Meaning

Blue

Set to a number between 0 and 255 of how blue the text should be.

Green

Set to a number between 0 and 255 of how green the text should be.

Red

Set to a number between 0 and 255 of how red the text should be.

Italic

If yes, the text will be italic.

Bold

If yes, the text will be bold.

Size

Sets the numeric size of the text.

Strike

If yes, the text will have line through it.

Underline

If yes, the text will be underlined.

FaceName

The font face of the text.

Here is an example that uses several TextStyle elements in Text controls:

Adding a tabbable control

Our InstallDlg still isn't ready. We need to add at least one control that can be tabbed to inside our Dialog element. For this, we can add a button like the Next button you saw before. It used the Publish element to take us to a dialog called SecondDlg:

<Control Id="Next"
Type="PushButton"
X="50"
Y="50"
Width="100"
Height="17">
<Publish Event="NewDialog"
Value="SecondDlg" />
</Control>

Suppose we don't have a SecondDlg though, and we just want a button that, when clicked, will continue the installation. It could say Install on it. For that, we'll create a button that publishes the EndDialog event with a Value of Return. This is illustrated in the following:

<Control Id="InstallButton"
Type="PushButton"
Text="Install"
Height="17"
Width="56"
X="245"
Y="243">
<Publish Event="EndDialog"
Value="Return" />
</Control>

We can also add a button that says Cancel. It will also publish the EndDialog event, but with a Value of Exit. If we add the Cancel attribute to it, this button will be triggered if the user clicks the X button on the window or presses Escape.

<Control Id="CancelButton"
Type="PushButton"
Text="Cancel"
Height="17"
Width="56"
X="180"
Y="243"
Cancel="yes">
<Publish Event="EndDialog"
Value="Exit" />
</Control>

Here's our InstallDlg now, ready for use:

Here's the entire markup:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="InstallDlg_UI">
<TextStyle Id="Tahoma_Regular"
FaceName="Tahoma"
Size="8" />
<Property Id="DefaultUIFont"
Value="Tahoma_Regular" />
<Dialog Id="InstallDlg"
Width="370"
Height="270"
Title="Amazing Software"
NoMinimize="no">
<Control Id="InstallButton"
Type="PushButton"
Text="Install"
Height="17"
Width="56"
X="245"
Y="243">
<Publish Event="EndDialog"
Value="Return" />
</Control>
<Control Id="CancelButton"
Type="PushButton"
Text="Cancel"
Height="17"
Width="56"
X="180"
Y="243"
Cancel="yes">
<Publish Event="EndDialog"
Value="Exit" />
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="InstallDlg"
Before="ExecuteAction" />
</InstallUISequence>
</UI>
</Fragment>
</Wix>

When adding controls it's important to know that the order in which they appear in your XML markup (from top to bottom) will be their tab order on the window. So, you should place the button you'd want to receive the focus first at the top of your markup, followed by the control that you'd want to receive the focus on next, down the line. In our example, the Install button would be focused when the window first loads and pressing Tab would take you to the Cancel button.

You can prevent a control from being the default focused control by setting its TabSkip attribute to yes.

Note that TabSkip only prevents a control from having the focus when the dialog is first shown. The user will still be able to tab to that control once the dialog is loaded.

WiX: A Developer's Guide to Windows Installer XML Create a hassle-free installer for your Windows software using WiX
Published: October 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on WiX, see here.)

Adding a progress dialog

So what happens when we click the Install button? It installs but there's no indication that anything has happened. We need a dialog that shows a progress bar to inform the user that the install is happening. Add a new WiX source file to your project and call it ProgressDlg.wxs. Add a UI element, like before, and then a Dialog element with the Id = "ProgressDlg" to differentiate it in the MSI database. The ProgressDlg.wxs file will look like the following:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="ProgressDlg"></Dialog>
</UI>
</Fragment>
</Wix>

Back in InstallDlg.wxs, add a DialogRef element inside the UI element to reference this new file:

<Fragment>
<UI ...>
<DialogRef Id="ProgressDlg" />

The Dialog element in ProgressDlg.wxs will use the Modeless attribute to signify that it shouldn't wait for user interaction. The installation process will continue, but it will allow this dialog to remain up for the remainder of the installation. This allows the dialog to respond to events that fire during the Execute sequence, which will enable the dialog's progress bar to increment itself.

<Dialog Id="ProgressDlg"
Width="370"
Height="270"
Title="Amazing Software"
Modeless="yes">

If you like, you can add a Cancel button to this dialog, just in case the user decides to cancel at this point. Refer back to InstallDlg for the markup. We'll also add a Control of type ProgressBar that uses the Subscribe element to receive progress updates:

<Control Id="MyProgressBar"
Type="ProgressBar"
X="70"
Y="150"
Width="200"
Height="20"
ProgressBlocks="yes">
<Subscribe Event="SetProgress"
Attribute="Progress" />
</Control>

By subscribing to the SetProgress event, the progress bar is able to increment itself as actions occur. Here's what it will look like:

Before, when we talked about adding a Next button to take us to a second dialog, there would have been no need to explicitly add that dialog to the UI sequence. The button takes us to it. It would have been up to that second dialog to then have an Install button that ended the dialog wizard and allowed the rest of the install to continue. In other words, we must always end with a button that publishes the EndDialog event with a Value of Return. Usually, that button is marked Install.

Our ProgressDlg, however, will remain up as the rest of the install continues. It's "Modeless". Therefore, we should schedule it to run after InstallDlg and before ExecuteAction. This is shown in the following code:

<InstallUISequence>
<Show Dialog="ProgressDlg"
After="InstallDlg" />
</InstallUISequence>

If you look at the InstallUISequence table in Orca, you can see how things look:

Even if we'd had a second, third, and fourth dialog, each arrived at by clicking a Next button on the dialog before, we wouldn't see any of them in this table. The InstallDlg is our entry point. When it closes, via the EndDialog event, ProgressDlg pops up. Since ProgressDlg is Modeless, ExecuteAction fires immediately and takes us into the Execute sequence. Here's a complete sample for the progress dialog:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="ProgressDlg"
Width="370"
Height="270"
Title="Amazing Software"
Modeless="yes">
<Control Id="CancelButton"
Type="PushButton"
TabSkip="no"
Text="Cancel"
Height="17"
Width="56"
X="180"
Y="243"
Cancel="yes">
<Publish Event="EndDialog"
Value="Exit" />
</Control>
<Control Id="MyProgressBar"
Type="ProgressBar"
X="70"
Y="150"
Width="200"
Height="20"
ProgressBlocks="yes">
<Subscribe Event="SetProgress"
Attribute="Progress" />
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="ProgressDlg"
After="InstallDlg" />
</InstallUISequence>
</UI>
</Fragment>
</Wix>

Modal windows

Up to this point, closing one dialog opened another in its place. You can also create "modal" windows that pop up on top of the current window. Instead of publishing the NewDialog event inside a button, such as with our Next button, we can publish the SpawnDialog event.

Modal windows are usually a little bit smaller in size than normal windows so that the parent window can be seen in the background. Suppose we had a dialog called PopupDlg; we could use the SpawnDialog event to open it modally. Typically, modal windows have an OK button that publishes the EndDialog event with a Value of Return. This allows them to be closed and have focus return to the parent window.

Here's what a button on InstallDlg would look like if it were set to open PopupDlg modally:

<Control Id="PopupButton"
Type="PushButton"
Text="Show Popup"
Height="17"
Width="56"
X="245"
Y="243"
Default="yes">
<Publish Event="SpawnDialog"
Value="PopupDlg" />
</Control>

Here's what the result looks like:

ICE20 revisited

ICE20 is the validation check that makes sure you have the necessary dialogs defined to handle things like showing a friendly message when the user cancels the install. We initially suppressed this check in the project's properties. Now, let's remove that suppression and add these dialogs. Note that all are defined in the WiX source files and you may find it easier to simply copy them to your project.

We need to define five dialogs: FilesInUse, Error, FatalError, UserExit, and Exit.

FilesInUse

The FilesInUse dialog allows the user to shut down applications that are accessing files the installer needs to update or delete. The MSI finds this dialog by looking in the MSI Dialog table for a dialog with an Id of FilesInUse. So, in our new WiX source file, the Dialog element's Id must match this name. The FilesInUseDlg.wxs file will look like like the following:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="FilesInUse"
Width="370"
Height="270"
Title="Amazing Software">
</Dialog>
</UI>
</Fragment>
</Wix>

To show which applications are using the files, we need to add a ListBox control that sets a property called FilesInUseProcess.

<Control Id="InUseFiles"
Type="ListBox"
Width="300"
Height="150"
X="30"
Y="60"
Property="FileInUseProcess"
Sorted="yes" />

We also need to add three buttons, Ignore, Retry, and Exit. Set the EndDialog event to these values:

<Control Id="Retry"
Type="PushButton"
X="304"
Y="243"
Width="56"
Height="17"
Default="yes"
Cancel="yes"
Text="Retry">
<Publish Event="EndDialog"
Value="Retry">1</Publish>
</Control>
<Control Id="Ignore"
Type="PushButton"
X="235"
Y="243"
Width="56"
Height="17"
Text="Ignore">
<Publish Event="EndDialog"
Value="Ignore">1</Publish>
</Control>
<Control Id="Exit"
Type="PushButton"
X="166"
Y="243"
Width="56"
Height="17"
Text="Cancel">
<Publish Event="EndDialog"
Value="Exit">1</Publish>
</Control>

Remember to add a DialogRef to this dialog in your InstallDlg.wxs file:

<DialogRef Id="FilesInUseDlg" />

Error

An installer uses the Error dialog to display error messages. Create a new source file and call it ErrorDlg.wxs. This file should set a property called ErrorDialog to the value you've set the Dialog element's Id. In addition, the Dialog element should set the ErrorDialog attribute to yes. The file should contain this snippet:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Property Id="ErrorDialog"
Value="ErrorDlg" />
<Dialog Id="ErrorDlg"
Width="370"
Height="270"
Title="Amazing Software"
ErrorDialog="yes">
</Dialog>
</UI>
</Fragment>
</Wix>

You'll also need to add a Text control inside the Dialog element and set its Id to ErrorText. This will be used to display the error message.

<Control Id="ErrorText"
Type="Text"
X="50"
Y="15"
Width="200"
Height="60" />

Next, add seven new buttons. Each will publish the EndDialog event with one of the following Values:

  • ErrorAbort
  • ErrorCancel
  • ErrorIgnore
  • ErrorNo
  • ErrorOk
  • ErrorRetry
  • ErrorYes

For example, here's the first that sets the ErrorAbort button:

<Control Id="A"
Type="PushButton"
X="100"
Y="80"
Width="56"
Height="17"
TabSkip="yes"
Text="Cancel">
<Publish Event="EndDialog"
Value="ErrorAbort">1</Publish>
</Control>

You can change the Text attribute of each button so that it matches the type, such as Yes for ErrorYes and No for ErrorNo. The X and Y attributes can remain the same. Remember to reference this new dialog with a DialogRef in your InstallDlg file.

FatalError

The FatalError dialog is shown when an unrecoverable error is encountered during the install, causing a premature end. Add a new WiX source file and call it FatalErrorDlg.wxs. The message will always be the same so you can add a Text control that displays a static message, as in the following example:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="FatalErrorDlg"
Width="370"
Height="270"
Title="Amazing Software">
<Control Id="Description"
Type="Text"
X="50"
Y="70"
Width="220"
Height="80"
Text="[ProductName] Setup Wizard ended
prematurely because of an error. Your system
has not been modified. To install this
program at a later time, run Setup Wizard
again." />
<Control Id="Finish"
Type="PushButton"
X="180"
Y="243"
Width="56"
Height="17"
Default="yes"
Cancel="yes"
Text="Finish">
<Publish Event="EndDialog"
Value="Exit" />
</Control>
</Dialog>
</UI>
<InstallUISequence>
<Show Dialog="FatalErrorDlg"
OnExit="error" />
</InstallUISequence>
<AdminUISequence>
<Show Dialog="FatalErrorDlg"
OnExit="error" />
</AdminUISequence>
</Fragment>
</Wix>

The Text control uses the Text attribute to set the message to display. You should also add a button that publishes the EndDialog event with a Value of Exit to allow the user to quit the install.

Notice that we add this dialog into two sequences: InstallUISequence and AdminUISequence. This is required even if you aren't supporting administrative installs. In both cases, set the Show element's OnExit attribute to error. This will schedule the dialog in the appropriate place in those sequences.

UserExit

The UserExit dialog appears when the user cancels the install. Typically, it contains some text and a Finish button that publishes the EndDialog event with a Value of Exit. Like the FatalError dialog, it must appear in both the InstallUISequence and the AdminUISequence. This time, we'll set the Show element's OnExit attribute to cancel.

Here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="UserExitDlg"
Width="370"
Height="270"
Title="Amazing Software">

<Control Id="Description"
Type="Text"
X="50"
Y="70"
Width="220"
Height="80"
Text="[ProductName] setup was interrupted. Your
system has not been modified. To install
this program at a later time, please run the
installation again." />

<Control Id="Finish"
Type="PushButton"
X="180"
Y="243"
Width="56"
Height="17"
Default="yes"
Cancel="yes"
Text="Finish">
<Publish Event="EndDialog"
Value="Exit" />
</Control>
</Dialog>
</UI>
<InstallUISequence>
<Show Dialog="UserExitDlg"
OnExit="cancel" />
</InstallUISequence>
<AdminUISequence>
<Show Dialog="UserExitDlg"
OnExit="cancel" />
</AdminUISequence>
</Fragment>
</Wix>

Exit

The Exit dialog is shown at the end of a successful installation. Typically, it contains some text and a Finish button. It must also be added to both the InstallUISequence and AdminUISequence. Here, set the Show element's OnExit attribute to success. Here's an example:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="ExitDlg"
Width="370"
Height="270"
Title="Amazing Software">

<Control Id="Description"
Type="Text"
X="50"
Y="70"
Width="220"
Height="80"
Text="[ProductName] setup has completed
successfully. Click 'Finish' to exit the
Setup Wizard." />

<Control Id="Finish"
Type="PushButton"
X="180"
Y="243"
Width="56"
Height="17"
Default="yes"
Cancel="yes"
Text="Finish">
<Publish Event="EndDialog"
Value="Exit" />
</Control>
</Dialog>
</UI>

<InstallUISequence>
<Show Dialog="ExitDlg"
OnExit="success" />
</InstallUISequence>

<AdminUISequence>
<Show Dialog="ExitDlg" OnExit="success" />
</AdminUISequence>
</Fragment>
</Wix>

Remember to add a DialogRef to reference this file in your InstallDlg file.

Summary

In this article, we covered the basics of making simple dialogs. There are a few required dialogs, as required by the ICE20 validation check, but for the most part you're free to create as many of your own customized dialogs as you want.


Further resources on this subject:


About the Author :


Nick Ramirez

Nick Ramirez is a software developer living in Columbus, Ohio. He believes that deployment should not be a moment of terror and has become a big fan of technologies like WiX. His other related interests include build automation, software architecture and playing Portal 2. Nick lives with his wife and two cats

Books From Packt


jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

PHP jQuery Cookbook
PHP jQuery Cookbook

Moodle 2.0 First Look
Moodle 2.0 First Look

Drupal 7
Drupal 7

Learning Ext JS 3.2
Learning Ext JS 3.2

PostgreSQL 9 Admin Cookbook
PostgreSQL 9 Admin Cookbook

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

OpenStreetMap
OpenStreetMap


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software