Wix 3.6 A Developers Guide To Windows In

Wix_3.6_a_developers_guide_to_windows_in

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 488

DownloadWix 3.6 A Developers Guide To Windows In
Open PDF In BrowserView PDF
www.it-ebooks.info

WiX 3.6: A Developer's Guide
to Windows Installer XML

An in-and-out, to-the-point introduction to Windows
Installer XML

Nick Ramirez

BIRMINGHAM - MUMBAI

www.it-ebooks.info

WiX 3.6: A Developer's Guide to Windows Installer XML
Copyright © 2012 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval
system, or transmitted in any form or by any means, without the prior written
permission of the publisher, except in the case of brief quotations embedded in
critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy
of the information presented. However, the information contained in this book is
sold without warranty, either express or implied. Neither the author, nor Packt
Publishing, and its dealers and distributors will be held liable for any damages
caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the
companies and products mentioned in this book by the appropriate use of capitals.
However, Packt Publishing cannot guarantee the accuracy of this information.

First published: October 2010
Second edition: December 2012

Production Reference: 1051212

Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham B3 2PB, UK.
ISBN 978-1-78216-042-7
www.packtpub.com

Cover Image by Abhishek Pandey (abhishek.pandey1210@gmail.com)

www.it-ebooks.info

Credits
Author

Project Coordinator

Nick Ramirez

Arshad Sopariwala

Reviewers

Proofreader

Neil Sleightholm

Maria Gould

Martin Oberhammer
Indexer

Paul Michniewicz

Rekha Nair

Roel van Bueren
ENG. Nir Bar

Production Coordinator
Arvindkumar Gupta

Acquisition Editor
Usha Iyer

Cover Work

Lead Technical Editor

Arvindkumar Gupta

Dayan Hyames
Technical Editor
Jalasha D'costa

www.it-ebooks.info

About the Author
Nick Ramirez is a software developer living in Columbus, Ohio. As a believer that

deployment shouldn't be a moment of terror, he has become a big fan of technologies
such as WiX. Other related interests include build automation, software architecture,
and playing Portal 2. Nick lives with his wife and two cats.
I would like to thank the hard-working folks at Packt Publishing.
Their organization and planning make all the difference! I would
also like to thank the dedicated people of the WiX community, who
tirelessly volunteer their time to answer questions. Finally, I would
like to thank the developers who contribute source code to the WiX
project. Their expertise and commitment have gone towards making
the best Windows deployment tool on the market.

www.it-ebooks.info

About the Reviewers
Neil Sleightholm is an IT consultant working in the UK. He has an engineering

background with experience in software development, application architecture,
electronics development, and mechanical engineering.

His current focus is on configuration management, build automation, installation
development, and deployment.
Neil has worked with most of the Microsoft platform technologies and has
programmed in C, C++, C#, Visual Basic, .NET, SQL, ASP.NET, and ASP. In the
build and source control field he has experience with NAnt, MSBuild, TeamBuild,
Subversion (SVN), TFS, VSS, Mercurial, and CVS. He has written installation systems
using Windows Installer, Windows Installer XML (WiX), Windows Installer Custom
Actions (using DTF), dotNetInstaller, InnoSetup, and Wise Installation System.
Neil has worked with open source projects and has been a contributor to
Windows Installer XML (WiX), dotNetInstaller, and the AlienBBC plugin
for Logitech Squeezebox.
In his spare time he is a petrol head and keen motorcyclist.
If you want to know more about him, you can check out his LinkedIn profile at:
http://www.linkedin.com/in/neilsleightholm.

Martin Oberhammer currently works as a Software Engineer at Sophos in
Vancouver, BC.

He studied computer science at the Johannes Kepler University in Linz, Austria,
where he graduated in 2002. His first job in software deployment was at Utimaco
Safeguard AG. In 2008, he moved to the USA and then to Canada, where he now
resides. Nick and Martin where at one point colleagues and created a software
installer using WiX technology.

www.it-ebooks.info

Paul Michniewicz is a software developer and educational consultant with
diverse experiences in academia, government, and industry.

As a developer, Paul has spent more than 12 years in software development and
testing. Much of that time was spent in configuration management where he has
managed source control systems, developed build and test automation strategies,
and authored several installers in the enterprise space for companies such as
JetForm and Adobe.
As an educational consultant, Paul has developed and delivered introductory
Java courses to professionals and students. He currently runs a tutoring business
where he teaches mathematics, physical sciences, and software development to
students of all ages. Paul has a special interest in working with students who have
developmental needs.
Paul lives in Ottawa, Canada with his wife Anne and two children Zygmunt
and Moira. He is currently a stay-at-home dad and homeschools his son. To know
more about Paul, you can check out his LinkedIn profile at ca.linkedin.com/in/
pmichnie.

Roel van Bueren works as senior consultant, trainer, and developer for
ROVABU NetWorks BV and ROVABU Software BV. Roel is specialized in Software
Packaging using Windows Installer and Flexera AdminStudio, Application and
Desktop Management by using Microsoft System Center Configuration Manager and
Novell ZENworks Configuration Management, Desktop Deployment of Microsoft
Windows XP, Windows 7, and Windows 8 by using Microsoft SCCM/MDT, Novell
ZENworks Configuration Management, ENGL Imaging Toolkit, and also Microsoft
.NET/C# development and application virtualization.
His latest projects involve "Bundle Commander" for Novell ZENworks
Configuration Management and "Setup Commander" for Microsoft System Center
Configuration Manager 2012, Microsoft Deployment Toolkit, and other deployment
solutions such as Dell KACE and RES Automation Manager, for which customized
transform files are needed to deploy MSI packages or silent switches to deploy
legacy setups.

www.it-ebooks.info

ENG. Nir Bar is a computer engineer, and graduate of Technion – Israel Institute
of Technology.

Nir Bar has over 13 years experience in software and hardware development.
He has worked with RAFAEL – Advanced Defense Systems, Marvell Technology
Group, Agilent Technologies, Applied Materials, McKesson, and other leading high
tech companies. He has worked in the Microsoft platform technologies and has
programmed in C, C++, C# .NET, and SQL Server.
In the Linux platform, Nir Bar has programmed in C, C++, and PERL.
He is also experienced in pre-Silicon verification methodologies and tools.
Currently, Nir is an independent software consultant, developer, and tutor.
He consults and develops software products from the idea stage through
analysis, design, development stages, and to ready-to-market products.
Nir Bar tutors Windows Installer technology to Israeli software companies.
To contact Nir Bar you can drop an e-mail to: nir.bar@panel-sw.co.il.
To my wife Sarit and to my sons Itay and Yehonathan for their love,
support, and encouragement.

www.it-ebooks.info

www.PacktPub.com
Support files, eBooks, discount offers and more

You might want to visit www.PacktPub.com for support files and downloads related
to your book.
Did you know that Packt offers eBook versions of every book published, with PDF
and ePub files available? You can upgrade to the eBook version at www.PacktPub.
com and as a print book customer, you are entitled to a discount on the eBook copy.
Get in touch with us at service@packtpub.com for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign
up for a range of free newsletters and receive exclusive discounts and offers on Packt
books and eBooks.

http://PacktLib.PacktPub.com

Do you need instant solutions to your IT questions? PacktLib is Packt's online
digital book library. Here, you can access, read and search across Packt's entire
library of books.

Why Subscribe?
•

Fully searchable across every book published by Packt

•

Copy and paste, print and bookmark content

•

On demand and accessible via web browser

Free Access for Packt account holders

If you have an account with Packt at www.PacktPub.com, you can use this to access
PacktLib today and view nine entirely free books. Simply use your login credentials
for immediate access.

www.it-ebooks.info

www.it-ebooks.info

www.it-ebooks.info

To my wife, Heidi, for her patience while I disappeared into research and writing.

www.it-ebooks.info

www.it-ebooks.info

Table of Contents
Preface
Chapter 1: Getting Started

Introducing Windows Installer XML
What is WiX?
Is WiX for you?
Where can I get it?
Visual Studio package (Votive)
A word about GUIDs
Your first WiX project
XML declaration and Wix element
The Product element
The Package element
The MediaTemplate element
The Media element
The Directory element
The Component element
The File element
The Feature element
Start menu shortcuts
Putting it all together
Adding a user interface
Viewing the MSI database
Orca.exe
Turning logging on during installation
Other resources
Summary

www.it-ebooks.info

1
7

8
8
9
10
13
16
16
17
18
20
21
22
23
27
29
30
33
37
40
41
41
42
43
43

Table of Contents

Chapter 2: Creating Files and Directories

45

Chapter 3: Putting Properties and AppSearch to Work

77

The File element
The DirectoryRef element
The ComponentGroup element
The Fragment element
Harvesting files with heat.exe
Copying and moving files
Copying files you install
Copying existing files
Moving existing files
Installing special-case files
Adding assembly files to the GAC
Installing a TrueType font
Installing 64-bit files
Creating an empty folder
Setting file permissions
Speeding up file installations
Summary

Custom properties
Declaring and setting properties
Referencing properties
Property visibility and scope
Secure properties
Property data types
Predefined Windows Installer properties
Implied properties
Cited properties
AppSearch
DirectorySearch
FileSearch
ComponentSearch
RegistrySearch
IniFileSearch
Summary

Chapter 4: Improving Control with Launch
Conditions and Installed States
The syntax of conditions
Condition syntax
Launch conditions

[ ii ]

www.it-ebooks.info

45
48
49
51
55
61
61
63
64
64
65
66
67
69
70
74
75

77
78
79
80
82
84
86
87
88
90
91
94
95
97
100
103

105
105
106
107

Table of Contents

Feature conditions
Component conditions
Action state
Installed state
Summary

Chapter 5: Understanding the Installation Sequence
InstallUISequence
UI standard actions
FindRelatedProducts
AppSearch
LaunchConditions
ValidateProductID
CostInitialize
FileCost
CostFinalize
MigrateFeatureStates
ExecuteAction

113
116
119
121
122

123
123
125

125
125
125
125
125
126
126
126
126

InstallExecuteSequence
Execute standard actions

126
128

Immediate versus deferred
Custom actions
Setting a Windows Installer property
Setting the location of an installed directory
Running embedded VBScript or JScript
Calling an external VBScript or JScript file
Calling a function from a dynamic-link library
Triggering an executable
Sending an error that stops the installation
Rollback custom actions
Accessing properties in a deferred action

130
131
133
134
135
137
138
140
142
143
144

InstallValidate
InstallInitialize
ProcessComponents
UnpublishFeatures
RemoveRegistryValues
RemoveShortcuts
RemoveFiles
InstallFiles
CreateShortcuts
WriteRegistryValues
RegisterUser
RegisterProduct
PublishFeatures
PublishProduct
InstallFinalize

[ iii ]

www.it-ebooks.info

128
128
128
128
128
129
129
129
129
129
129
129
130
130
130

Table of Contents

Adding conditions to custom actions
Deployment Tools Foundation
The session object
Getting and setting properties
Logging
Showing a message box
Accessing feature and component states
Querying the MSI database
Inserting rows into the MSI database
Summary

146
147
147
148
148
149
150
151
151
153

Chapter 6: Adding a User Interface

155

Chapter 7: Using UI Controls

187

WiX standard dialog sets
WixUI_Advanced
WixUI_FeatureTree
WixUI_InstallDir
WixUI_Mondo
Customizing a standard dialog set
Creating your own dialogs
ICE20 errors
Adding dialog files
The Dialog element
Scheduling dialogs
Adding TextStyle elements
Adding a tabbable control
Adding a progress dialog
Modal windows
ICE20 revisited
FilesInUse
Error
FatalError
UserExit
Exit
Summary
Attributes common to all controls
Specific control syntax
PushButton
Text
ScrollableText
Line

155
156
158
159
160
161
163
163
164
165
166
167
169
172
175
177
177
179
181
182
183
185

187
189
189
192
193
194

[ iv ]

www.it-ebooks.info

Table of Contents

GroupBox
Bitmap
Icon
Edit
MaskedEdit
PathEdit
CheckBox
RadioButtonGroup
ComboBox
ListBox
ListView
DirectoryList
DirectoryCombo
SelectionTree
VolumeCostList
VolumeSelectCombo
Billboard
ProgressBar
Summary

195
195
197
197
199
201
202
203
205
206
207
208
211
212
215
216
218
222
226

Chapter 8: Tapping into Control Events

227

Chapter 9: Working from the Command Line

247

Publishing control events
Subscribing to control events
Publish events
DoAction
EndDialog
NewDialog
AddLocal
Publishing a property
Subscribe events
ScriptInProgress
SelectionAction
TimeRemaining
Summary

Candle.exe
Response files
.wixobj files
Command-line arguments (compiling)
-arch
-d
-ext

[v]

www.it-ebooks.info

227
231
232
233
234
235
236
239
239
240
242
243
246
247
249
250
250

251
251
251

Table of Contents
-fips
-I
-nologo
-o
-p
-pedantic
-sfdvital
-ss
-sw
-trace
-v
-wx

Compile-time variables
Custom compiler variables
Environment variables
System variables
Conditional statements and iterations
if...elseif...else
ifdef
ifndef
Iterations
Errors and warnings
Preprocessor extensions
Light.exe
Command-line arguments (linking)
-b
-bf
-binder
-cultures
-d
-dut
-ext
-loc
-nologo
-notidy
-o[ut]
-pedantic
-sadmin
-sadv
-sloc
-sma
-ss
-sts
-sui
-sv
-sw[N]
-usf 

[ vi ]

www.it-ebooks.info

251
251
252
252
252
252
252
252
253
253
253
253

253
253
254
255
255
255
256
256
257
258
258
264
265

265
265
265
266
266
266
266
266
266
267
267
267
267
267
267
267
268
268
268
268
268
269

Table of Contents
-v
-wx[N]
-xo

Command-line arguments (binding)
-bcgg
-cc 
-ct 
-cub 
-dcl:level
-eav
-fv
-ice 
-pdbout 
-reusecab
-sa
-sacl
-sf
-sh
-sice: 
-sl
-spdb
-sval

Link-time variables
Localization variables
Binder variables
Custom linker variables
Building an installer without Visual Studio
Summary

269
269
269

269

269
270
270
270
270
270
270
271
271
271
271
271
272
272
272
272
272
272

273
273
273
275
276
278

Chapter 10: Accessing the Windows Registry

279

Chapter 11: Controlling Windows Services

293

Reading from the registry
Writing to the registry
Writing a single value
Writing multiple values
Setting NeverOverwrite
Removing registry values
Remove all keys recursively
Removing a single value
Copying registry values
Registry permissions
Summary

Creating a simple Windows service
Using sc.exe
Using WiX to install a service

[ vii ]

www.it-ebooks.info

280
282
283
284
287
287
287
288
289
290
292
293
296
298

Table of Contents

Starting, stopping, and uninstalling a service
Setting the service's user account
Adding service dependencies
Service recovery with Util:ServiceConfig
Summary

300
303
307
310
313

Chapter 12: Localizing Your Installer

315

Chapter 13: Upgrading and Patching

341

Chapter 14: Extending WiX

359

WiX localization files
The role of Light.exe
Setting language and code page attributes
The Package element
The Product element
Localizing the UI
Error messages
Progress bar messages
EULA
Resizing controls
Creating a multi-language MSI
Summary
Planning for updates
Choosing an update type
Per-user or per-machine
Preparing a major upgrade
The minor upgrade
Authoring a .wixmsp file
Creating a patch from .wixpdb files
Creating a patch from .wixout files
The small update
Summary

Building a custom WiX extension
Setting the stage
Extending the CompilerExtension class
Adding an XML schema
Parsing custom elements
Creating a new MSI table
Extending the WixExtension class
Using the extension in a WiX project
Tying a custom action to the custom element
Summary
[ viii ]

www.it-ebooks.info

315
319
321
322
325
326
326
329
332
334
336
339
341
342
343
343
350
350
353
356
358
358
359
360
360
362
365
370
372
374
376
383

Table of Contents

Chapter 15: Bootstrapping Prerequisites with Burn

385

Chapter 16: Customizing the Burn UI

419

Index

449

Using the Bootstrapper Project template
Describing the Bundle element
Restricting the install by the operating system
UpgradeCode and detecting related bundles
Updating existing bundles
Finding other related bundles
Where the packages are cached
Chaining packages
The Chain element
The MsiPackage element
The ExePackage element
The MspPackage element
The MsuPackage element
Downloading packages
Counting package references
Rollback boundaries
PackageGroups
The Standard Bootstrapper UI
The RtfLicense user interface
The HyperlinkLicense user interface
Summary
Burn extension points
Creating the class library
Extending the BootstrapperApplication class
Defining the model
Implementing the viewmodel
Declaring the properties and fields
Defining the constructor
Setting up the event handlers
Helper methods
Marking up the view
Referencing the UI in a Burn bundle
Passing user input to a bundled MSI
Displaying progress
Downloading packages
Collecting command-line arguments
Summary

[ ix ]

www.it-ebooks.info

386
387
389
391
391
396
397
398
398
400
402
405
406
407
410
412
413
415
415
416
418
419
420
422
425
427
432
434
435
438
439
441
442
444
446
447
448

www.it-ebooks.info

Preface
Since Rob Mensching offered up the WiX toolset as the first open source project
from Microsoft in 2004, it has been quietly gaining momentum and followers.
Today, thousands use it to build Window Installer packages from simple XML
elements. Gone are the days when you would have had to pay for software to
build an installer for you. Now, you can do it yourself for cheap.
Not only that, but WiX has matured into a fairly slick product that's sufficiently easy
to use. Best of all, it has the bells and whistles you want, including functionality to
add user interface wizards, Start menu shortcuts, control Windows services, and
read and write to the registry.
This new edition, WiX 3.6: A Developer's Guide to Windows Installer XML, brings
you up-to-date on the latest changes to the toolset. Whether you're new to WiX or
an established pro, you're likely to find new insights. Each chapter gets straight to
the point, giving you hands-on experience, so you'll master the technology quickly.

What this book covers

Chapter 1, Getting Started, explains how after downloading and installing the WiX
toolset, you'll start using it right away to create a simple installer. Then, you'll see
how to add a basic user interface to it, install it with logging turned on, and view its
internal database.
Chapter 2, Creating Files and Directories, gives you a deeper understanding of how files
are installed and the best way to organize them in your project. You'll then use the
tool Heat.exe to generate WiX markup. Last, you'll learn about copying and moving
files, and installing special-case files.

www.it-ebooks.info

Preface

Chapter 3, Putting Properties and AppSearch to Work, introduces you to Windows
Installer properties, including those that are defined automatically and those that are
invented by you. Afterwards, you'll check the end user's computer for specific files,
directories, registry keys, and INI file settings using AppSearch.
Chapter 4, Improving Control with Launch Conditions and Installed States, teaches you to
leverage conditional statements to set prerequisites for running your installer or to
exclude particular features or components from the install. You'll also discover how
to check the action state and installed state of your features and components.
Chapter 5, Understanding the Installation Sequence, gives you a clear picture of how the
whole installation process works as you examine the order and meaning of installer
actions. You will then create custom actions and add them to this built-in sequence.
Then, you'll learn the basics of using the Deployment Tools Foundation library for
writing custom action code in C#.
Chapter 6, Adding a User Interface, after giving you a quick introduction to the
standard dialogue wizards that come with the WiX toolset, shows how to build
your own from scratch. You'll learn all of the required elements for displaying
dialogs and linking them together. You'll also see how to display common messages
such as errors and cancellation confirmations.
Chapter 7, Using UI Controls, gives you hands-on experience with each type of
UI control including buttons, textboxes, and progress bars.
Chapter 8, Tapping into Control Events, breathes life into your UI controls by having
them publish and subscribe to events. We'll get details on what each event does and
take a closer look at those you'll use on a routine basis.
Chapter 9, Working from the Command Line, emphasizes the fact that we don't
particularly need Visual Studio to compile our projects. We'll cover the commands
necessary to build an installer from the command line using Candle.exe, our
compiler, and Light.exe, our linker/binder. We will also explore how to use
preprocessor statements and how to create a custom preprocessor extension.
Chapter 10, Accessing the Windows Registry, illustrates how our installer may read
and write to the Windows Registry. We'll add and remove keys, copy values, and
set permissions.
Chapter 11, Controlling Windows Services, provides some solid examples for installing
and interacting with Windows services. You'll see how to set the service's user
account, add service dependencies, and set failure recovery.
Chapter 12, Localizing Your Installer, tackles how to render your UI for different
languages and how Light.exe, the WiX linker, plays a role. You'll then get involved
in making a single multi-language installer.
[2]

www.it-ebooks.info

Preface

Chapter 13, Upgrading and Patching, covers the all-so-important topic of upgrading
and patching. You'll get the low down on major upgrades, minor upgrades, and
small updates.
Chapter 14, Extending WiX, jumps into adding new, custom XML elements for
extending the core functionality of WiX. We'll write a library, using C#, that takes
our installer to places it's never been.
Chapter 15, Bootstrapping Prerequisites with Burn, discusses the new bootstrapping
functionality called Burn. We'll create a single executable that installs all necessary
prerequisites for our software.
Chapter 16, Customizing the Burn UI, solves the problem of customizing our Burn user
interface by crafting a new one using C# and WPF. We'll discover the places where
we can hook into the bootstrapper engine and how best to pass information from the
user to our installation packages.

What you need for this book

In order to both write and run the code demonstrated in this book, you will need
the following:
•

Visual Studio 2005 or newer (Standard Edition or higher)

•

The WiX toolset, which can be downloaded from http://wixtoolset.org/

Who this book is for

If you are a developer and want to create installers for software targeting the
Windows platform, then this book is for you. Those new to WiX and Windows
Installer should feel right at home as we start with the basics and gradually work
up to more complex subjects. Others with more experience will benefit as we
catalog the new features in WiX 3.6. If you're coming from an earlier version of WiX,
you'll be happy to know that for the most part, things that used to work will still
work. However, several tasks, such as implementing a major upgrade, have been
simplified. We'll highlight the big changes, but keep an eye on familiar elements as
some subtle changes have been made.

[3]

www.it-ebooks.info

Preface

Conventions

In this book, you will find a number of styles of text that distinguish between
different kinds of information. Here are some examples of these styles, and an
explanation of their meaning.
Code words in text are shown as follows: "If you would like conditions to be
re-evaluated during a re-install, you should set the Transitive attribute on
the parent component to yes."
A block of code is set as follows:







When we wish to draw your attention to a particular part of a code block, the
relevant lines or items are set in bold:



MyProperty = 1


Any command-line input or output is written as follows:
msiexec /i myInstaller.msi /l*v install.log

[4]

www.it-ebooks.info

Preface

New terms and important words are shown in bold. Words that you see on the
screen, in menus or dialog boxes for example, appear in the text like this: "using the
Add Reference option in Solution Explorer".
Warnings or important notes appear in a box like this.

Tips and tricks appear like this.

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about
this book—what you liked or may have disliked. Reader feedback is important for
us to develop titles that you really get the most out of.
To send us general feedback, simply send an e-mail to feedback@packtpub.com,
and mention the book title through the subject of your message.
If there is a topic that you have expertise in and you are interested in either writing
or contributing to a book, see our author guide on www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to
help you to get the most from your purchase.

Downloading the example code

You can download the example code files for all Packt books you have purchased
from your account at http://www.packtpub.com. If you purchased this book
elsewhere, you can visit http://www.packtpub.com/support and register to have
the files e-mailed directly to you.

[5]

www.it-ebooks.info

Preface

Errata

Although we have taken every care to ensure the accuracy of our content, mistakes
do happen. If you find a mistake in one of our books—maybe a mistake in the text or
the code—we would be grateful if you would report this to us. By doing so, you can
save other readers from frustration and help us improve subsequent versions of this
book. If you find any errata, please report them by visiting http://www.packtpub.
com/support, selecting your book, clicking on the errata submission form link, and
entering the details of your errata. Once your errata are verified, your submission
will be accepted and the errata will be uploaded to our website, or added to any list
of existing errata, under the Errata section of that title.

Piracy

Piracy of copyright material on the Internet is an ongoing problem across all media.
At Packt, we take the protection of our copyright and licenses very seriously. If you
come across any illegal copies of our works, in any form, on the Internet, please
provide us with the location address or website name immediately so that we can
pursue a remedy.
Please contact us at copyright@packtpub.com with a link to the suspected
pirated material.
We appreciate your help in protecting our authors, and our ability to bring you
valuable content.

Questions

You can contact us at questions@packtpub.com if you are having a problem with
any aspect of the book, and we will do our best to address it.

[6]

www.it-ebooks.info

Getting Started
Windows Installer XML (WiX) is a free, open source XML markup that's used to
author installation packages for Windows-based software. The underlying technology
is called Windows Installer, which is the established standard for installing to any
Windows operating system. Until recently, WiX was a Microsoft offering, but is
now supported by the non-profit Outercurve Foundation. It is used by countless
companies around the world. Microsoft uses it to deploy its own software including
Microsoft Office and Visual Studio. In fact, Microsoft uses WiX for these products.
Windows Installer has many features, but how do you leverage them? How do you
even know what they are? This book will help you by making you more familiar
with the wide range of capabilities that are available. The good news is that WiX
makes many of the arcane and difficult-to-understand aspects of the Windows
Installer technology simple to use. This book will teach you the WiX syntax so that
you can create a professional-grade installer that's right for you.
In this chapter, we will cover the following topics:
•

Getting WiX and using it with Visual Studio

•

Creating your first WiX installer

•

Examining an installer database with Orca

•

Logging an installation process

•

Adding a simple user interface

www.it-ebooks.info

Getting Started

Introducing Windows Installer XML

In this section, we'll dive right in and talk about what WiX is, where to get it, and
why you'd want to use it when building an installation package for your software.
We'll follow up with a quick description of the WiX tools and the new project types
made available in Visual Studio.

What is WiX?

Creating a Windows Installer, or MSI package, has always been a challenging task. The
package is actually a relational database that describes how the various components of
an application should be unpacked and copied to the end user's computer.
In the past you had two options:
•

You could try to author the database yourself—a path that requires a
thorough knowledge of the Windows Installer API.

•

You could buy a commercial product such as InstallShield to do it for you.
These software products will take care of the details, but you'll forever be
dependent on them. There will always be parts of the process that are
hidden from you.

WiX offers a route that exists somewhere in the middle. Abstracting away the
low-level function calls while still allowing you to write much of the code by hand,
WiX is a framework for building an installer in ways that mere mortals can grasp.
Best of all, it's free. As an open source product, it has quickly garnered a wide user
base and a dedicated community of developers. Much of this has to do not only with
its price tag but also with its simplicity. It can be authored in a simple text editor
(such as Notepad) and compiled with the tools provided by WiX. As it's a flavor of
XML, it can be read by humans, edited without expensive software, and lends itself
to being stored in source control where it can be easily merged and compared.
The examples in this first chapter will show how to create a simple installer with
WiX using Visual Studio. However, later chapters will show how you can build your
project from the command line using the compiler and linker from the WiX toolset.
The WiX source code is available for download, so you can be assured that nothing
about the process will be hidden if you truly need to know more about it.

[8]

www.it-ebooks.info

Chapter 1

Is WiX for you?

It's fairly simple to copy files to an end user's computer. If that's all your product
needs, then the Windows Installer technology might be overkill. However, there are
many benefits to creating an installable package for your customers, some of which
might be overlooked. The following is a list of features that you get when you author
a Windows Installer package with WiX:
•

All of your executable files can be packaged into one convenient bundle,
simplifying deployment

•

Your software is automatically registered with Programs and Features

•

Windows takes care of uninstalling all of the components that make up your
product when the user chooses to do so

•

If files for your software are accidently removed, they can be replaced by
right-clicking on the MSI file and selecting Repair

•

You can create different versions of your installer and detect which version
has been installed

•

You can create patches to update only specific areas of your application

•

If something goes wrong while installing your software, the end user's
computer can be rolled back to a previous state

•

You can create Wizard-style dialogs to guide the user through the installation

Many people today simply expect that your installer will have these features. Not
having them could be seen as a real deficit. For example, what is a user supposed to
do when they want to uninstall your product but can't find it in the Programs and
Features list and there isn't an uninstall shortcut? They're likely to remove files in a
haphazard manner and wonder why you didn't make things easy for them.
Maybe you've already figured that Windows Installer is the way to go, but why WiX?
One of my favorite reasons is that it gives you greater control over how things work.
You get a much finer level of control over the development process. Commercial
software that does this for you also produces an MSI file but hides the details about
how it was done. It's analogous to crafting a website. You get much more control when
you write the HTML yourself as opposed to using a WYSIWYG software.
Even though WiX gives you more control, it doesn't make things overly complex.
You'll find that making a simple installer is very straightforward. For more
complicated projects, the parts can be split up into multiple XML source files to
make it easier to work with. Going further, if your product is made up of multiple
applications that will be installed together as a suite, you can compile the different
chunks into libraries that can be merged together into a single MSI file. This allows
each team to isolate and manage its part of the installation package.
[9]

www.it-ebooks.info

Getting Started

WiX is a stable technology, having been first released to the public in 2004, so you
don't have to worry about it disappearing. It's also had a steady progression of version
releases. These are just some of the reasons why you might choose to use WiX.

Where can I get it?

You can find the latest version of WiX at http://wixtoolset.org/, which has
both stable releases and weekly builds. The current release is Version 3.6. Once
you've downloaded the WiX installer package, double-click on it to launch it.
It relies on having an Internet connection to download the .NET 4.0 platform,
if it's not already installed.
If you want to install on a computer that isn't connected to the Internet, first download
the installer on a computer that is and then open a command prompt and run the WiX
executable with the following command wix36.exe /layout LayoutDirectory.
The layout option takes the name of a target directory where the WiX files will be
downloaded to. You can then take these files (which include a new installer) to the
computer that doesn't have an Internet connection and use them there.

[ 10 ]

www.it-ebooks.info

Chapter 1

This installs all of the necessary files needed to build WiX projects. You'll also get the
WiX SDK documentation and the settings for Visual Studio IntelliSense and project
templates. Version 3.6 supports Visual Studio versions 2005 through 2012, although
not the Express editions.
WiX comes with the tools outlined in the following table:
Tool
Candle.exe

What it does

Light.exe

Links and binds .wixobj files to create a final .msi file.
Also creates cabinet files and embeds streams in an MSI
database

Lit.exe

Creates WiX libraries (.wixlib) that can be linked together
by Light

Dark.exe

Decompiles an MSI file into WiX code

Heat.exe

Creates a WiX source file that specifies components from
various inputs

Insignia.exe

Inscribes an MSI with the digital signatures that its external
CAB files are signed with

Melt.exe

Converts a merge module (.msm) into a component group in
a WiX source file

Torch.exe

Generates a transform file used to apply changes to an
in-progress installation or to create a patch file

Shine

Creates a DGML diagram from an MSI

Smoke.exe

Runs validation checks on an MSI or MSM file

Pyro.exe

Creates a patch file (.msp) from .wixmsp and .wixmst files

WixCop.exe

Converts Version 2 WiX files to Version 3

WixUnit.exe

Validates WiX source files

Lux.exe and Nit.exe

Authors and runs unit tests on custom actions

Compiles WiX source files (.wxs) into intermediate object
files (.wixobj)

[ 11 ]

www.it-ebooks.info

Getting Started

In order to use some of the functionality in WiX, you may need to download a
more recent version of Windows Installer. You can check your current version
by viewing the help file for msiexec.exe, which is the Windows Installer service.
Open a Windows command prompt and then type msiexec /? to bring up a
window, as shown in the following screenshot:

If you'd like to install a newer version of Windows Installer, you can get it from the
Microsoft Download Center website. Go to:
http://www.microsoft.com/downloads/en/default.aspx

Search for Windows Installer. The current version for Windows XP, Vista, Server
2003, and Server 2008 is 4.5. Windows 7, Windows Server 2008 R2, and Windows 8
can support Version 5.0. Each new version is backwards compatible and includes the
features from earlier editions.

[ 12 ]

www.it-ebooks.info

Chapter 1

Visual Studio package (Votive)

The WiX toolset provides files that update Visual Studio to provide new WiX
IntelliSense and project templates. Together these features, which are installed for
you along with the other WiX tools, are called Votive. You must have Visual Studio
2005 or newer. Votive won't work on the Express versions. Refer to the WiX site for
more information:
http://wix.sourceforge.net/votive.html

After you've installed WiX, you should see a new category of project types in
Visual Studio labeled under the title Windows Installer XML, as shown in the
following screenshot:

There are seven new project templates:
•

Setup Project: Creates a Windows Installer package from one or more
WiX source files

•

Merge Module Project: Creates a merge module (MSM) file

•

Setup Library Project: Creates a .wixlib library

•

Bootstrapper Project: Creates a prerequisite bootstrapper

•

C# Custom Action Project: Creates a .NET custom action in C#

•

C++ Custom Action Project: Creates an unmanaged C++ custom action

•

VB Custom Action Project: Creates a VB.NET custom action
[ 13 ]

www.it-ebooks.info

Getting Started

Using these templates is certainly easier than creating the files on your own with
a text editor. To start creating your own MSI installer, select the template Setup
Project. This will create a new .wxs (WiX source file) for you to add XML markup
to. Once we've added the necessary markup, you'll be able to build the solution by
selecting Build Solution from the Build menu or by right-clicking on the project
in the Solution Explorer and selecting Build. Visual Studio will take care of calling
candle.exe and light.exe to compile and link your project files.
If you right-click on your WiX project in Solution Explorer and select Properties,
you'll see several screens where you can tweak the build process. One thing you'll
want to do is set the amount of information that you'd like to see when compiling
and linking the project, and how non-critical messages are treated. Refer to the
following screenshot:

Here we're selecting the level of messages that we'd like to see. To see all warnings
and messages, set Warning Level to Pedantic. You can also check the Verbose
output checkbox to get even more information. Checking Treat warnings as errors
will cause warning messages that normally would not stop the build to be treated as
fatal errors.

[ 14 ]

www.it-ebooks.info

Chapter 1

You can also choose to suppress certain warnings. You'll need to know the specific
warning message number though. If you get a build-time warning, you'll see the
warning message, but not the number. One way to get it is to open the WiX source
code (available at http://wix.codeplex.com/releases/view/93929) and view the
messages.xml file in the src\wix\Data folder. Search the file for the warning and
from there you'll see its number. Note that you can suppress warnings but not errors.
Another feature of WiX is its ability to run validity checks on the MSI package.
Windows Installer uses a suite of tests called Internal Consistency Evaluators (ICEs)
for this. These checks ensure that the database as a whole makes sense and that
the keys on each table join correctly. Through Votive, you can choose to suppress
specific ICE tests. Use the Tools Setting page of the project's properties as shown in
the following screenshot:

In this example, ICE test 102 is being suppressed. You can specify more than one test
by separating them with semicolons. To find a full list of ICE tests, go to MSDN's ICE
Reference web page at:
http://msdn.microsoft.com/en-us/library/aa369206%28VS.85%29.aspx

[ 15 ]

www.it-ebooks.info

Getting Started

The Tool Settings screen also gives you the ability to add compiler or linker
command-line flags. Simply add them to the textboxes at the bottom of the screen.
We will discuss command-line arguments for Candle and Light later in the book.

A word about GUIDs

In various places throughout WiX, you'll be asked to provide a GUID, which is a
Globally Unique Identifier. This is so that when your product is installed on the end
user's computer, references to it can be stored in the Windows Registry without the
chance of having name conflicts. By using GUIDs, Windows Installer can be sure that
every software application, and even every component of that software, has a unique
identity on the system.
Each GUID that you create on your computer is guaranteed to be different from a
GUID that someone else would make. Using this, even if two pieces of software, both
called "Amazing Software", are installed on the same computer, Windows will be
able to tell them apart.
Visual Studio 2010 provides a way to create a GUID. Go to Tools | Create GUID
and copy a new GUID using Registry Format. WiX can accept a GUID with or
without curly brackets around it, as 01234567-89AB-CDEF-0123-456789ABCDEF or
{01234567-89AB-CDEF-0123-456789ABCDEF}. In this book, I'll display real GUIDs,
but you should not re-use them as then your components will not be guaranteed to
be unique.

Your first WiX project

To get started, download the WiX toolset. It can be found at:
http://wixtoolset.org/

Once you've downloaded and installed it, open Visual Studio and select New
Project | Windows Installer XML | Setup Project. This will create a project with a
single .wxs (WiX source) file. Visual Studio will usually call this file Product.wxs,
but the name could be anything as long as it ends with .wxs.
Even the most minimal installer must have the following XML elements:
•

An XML declaration

•

A Wix element that serves as the root element in your XML document

•

A Product element that is a child to the Wix element, but all other elements
are children to it

•

A Package element
[ 16 ]

www.it-ebooks.info

Chapter 1

•

A Media or MediaTemplate element

•

At least one Directory element with at least one child Component element

•

A Feature element

XML declaration and Wix element

Every WiX project begins with an XML declaration and a Wix element:




Downloading the example code
You can download the example code files for all Packt books you have
purchased from your account at http://www.packtpub.com. If you
purchased this book elsewhere, you can visit http://www.packtpub.
com/support and register to have the files e-mailed directly to you.

The xmlns, or XML namespace, just brings the core WiX elements into the local scope
of your document. At the bottom of the file you'll have to close the Wix element, of
course. Otherwise, it's not valid XML. The Wix element is the root element of the
document. It comes first and last. All other elements will be nested inside of it.
For the most part, knowing only the basic rules of writing a
well-formed XML document will be enough to get you up
and running using WiX. The major points are as follows,
as recommended by the W3C:
•
•
•
•
•

The document must begin and end with the same root
element
All elements must have a matching closing tag or be
closed themselves
XML tags are case sensitive
Elements must be properly nested, with inner elements
not overlapping outer elements
XML attributes should be quoted

At this point, you could also add the RequiredVersion attribute to the Wix
element. Given a WiX toolset version number, such as "3.6.3303.0", it won't let
anyone compile the .wxs file unless they have that version or higher installed.
If, on the other hand, you're the only one compiling your project, then it's no
big deal.
[ 17 ]

www.it-ebooks.info

Getting Started

The Product element
Next, add a Product element.






This is where you define the characteristics of the software you're installing: its
name, language, version, and manufacturer. The end user will be able to see these
properties by right-clicking on your MSI file, selecting Properties, and viewing the
Summary tab. Most of the time, these values will stay the same from one build of
your project to the next. The exception is when you want to increment the software's
version to indicate that it's an upgrade of a previous installation. In that case, you
need to only change the Version attribute, and sometimes the Id attribute. We'll talk
more about upgrading previous installations later on in the book.
The Product element's Id attribute represents the so-called ProductCode of your
software. It's always a unique number—a GUID—that Windows will use to uniquely
identify your software (and tell if it's already installed on the computer). You can
either hardcode it, like here, or just put an asterisk. That way, WiX will pick a new
GUID for you each time you compile the project.





The Name attribute defines the name of the software. In addition to being displayed
in the MSI file's Properties page, it will also be shown in various places throughout
the user interface of your installer—that is, once you've added a user interface, which
we'll touch on at the end of this chapter.

[ 18 ]

www.it-ebooks.info

Chapter 1

The Language attribute is used to display error messages and progress information
in the specified language to the user. It's a decimal language ID (LCID). A full list can
be found on Microsoft's LCID page at:
http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx

The previous example used "1033", which stands for "English-United States". If your
installer uses characters not found in the ASCII character set, you'll also need to add
a Codepage attribute set to the code page that contains those characters. Don't worry
too much about this now. We'll cover languages and code pages later in the book
when we talk about localization.
The Version attribute is used to set the version number of your software. It can
accept up to four numbers separated by periods. Typically, when you make a big
enough change to the existing software, you'll increment the number. Companies
often use the [MajorVersion].[MinorVersion].[Build].[Revision] format, but
you're free to use any numbering system you like.
During upgrade scenarios, the fourth digit in the Version
attribute is ignored and won't make a difference when detecting
previously installed software.

The Manufacturer attribute tells the user who this software is from and usually
contains the name of your company. This is another bit of information that's
available via the MSI file's Properties page.
The final attribute to consider is UpgradeCode. This should be set to a GUID and will
identify your product across releases. It remains constant for a product line, even
among different product versions. Think: Microsoft Office 2007 and Office 2010. Both
would have the same UpgradeCode. Therefore, it should stay the same even when
the ProductCode and Version change.
Windows will use this number in its efforts to keep track of all the software installed
on the machine. WiX has the ability to search for previously installed versions of not
only your own software, but also those created by others and it uses UpgradeCode to
do it. Although, technically, this is an optional attribute, you should always supply it.

[ 19 ]

www.it-ebooks.info

Getting Started

The Package element

Once you've defined your Product element, the next step is to nest a Package
element inside. An example is shown as follows:






Of the attributes shown in this example, only Compressed is really required. By
setting Compressed to yes, you're telling the installer to package all of the MSI's
resources into CAB files. Later, you'll define these CAB files with Media elements
or a MediaTemplate element.
Technically, an Id attribute is also required, but by omitting it you're letting WiX
create one for you. You'd have to create a new one anyway since every time you
change your software or the installer in any way, the package (the MSI file) has
changed and so the package's ID must change. This really, in itself, emphasizes what
the Package element is. Unlike the Product element, which describes the software
that's in the installer, the Package element describes the installer itself. Once you've
built it, you'll be able to right-click on the MSI and select Properties to see the
attributes you've set here.
The InstallerVersion attribute can be set to require a specific version of msiexec.
exe (the Windows Installer service that installs the MSI when you double-click on it)
to be installed on the end user's computer. If they have an older version, Windows
Installer will display a dialog telling them that they need to upgrade. It will also
prevent you from compiling the project unless you also have this version installed
on your own computer. The value can be found by multiplying the major version
by 100 and adding the minor version. So, for Version 4.5 of msiexec.exe, you'd set
InstallerVersion to 405.

[ 20 ]

www.it-ebooks.info

Chapter 1

The InstallScope attribute can be set to either perMachine or perUser. The former
means that your software will be installed in the "All Users" context, meaning that
all users will be able to access your application. As such, the person performing the
install will need elevated privileges on a UAC enabled system such as Windows 7 to
continue the installation. The latter means that it will be installed only for the current
user. Behind the scenes this is setting a WiX property called ALLUSERS that we'll
cover in more detail later when we discuss properties.
The rest of the attributes shown provide additional information for the MSI
file's Properties window. Manufacturer is displayed in the Author text field,
Description is shown as Subject, Keywords show up as Keywords, and Comments
show as Comments. It's usually a good idea to provide at least some of this
information, if just to help you distinguish one MSI package from another.

The MediaTemplate element

The files that you intend to install are compressed into CAB files and shipped along
with the installer. You decide whether to embed them inside the MSI or provide
them visibly alongside it. In WiX 3.6, a single MediaTemplate element handles all the
details for you, intelligently splitting your files into the prescribed number of CAB
files. Add it after the Package element, as shown in the following code snippet:







The EmbedCab attribute is optional and sets whether the CAB files will be embedded
inside the MSI, the default being to not embed them. Either way, WiX will create up
to 999 CAB files, each holding a maximum of 200 MB of data. You can change that
limit with the MaximumUncompressedMediaSize attribute, set to a size in megabytes.
If a single file is bigger than the maximum, it will be placed into its own CAB file
with enough space to accommodate it.
If you want to split your installation up into several physical disks—conjure up
images of "Please insert disk 2"—you want to use the Media element instead.

[ 21 ]

www.it-ebooks.info

Getting Started

The Media element

The Media element is an older element that was replaced by MediaTemplate and if
you use one you can't use the other. However, in some cases, the Media element is
the only thing for the job. For each Media element that you add to your WiX markup,
a new CAB file will be created.







Each Media element gets a unique Id attribute to distinguish it in the MSI Media
table. It must be a positive integer. If the files that you add to your installation
package don't explicitly state which CAB file they wish to be packaged into, they'll
default to using a Media element with an Id value of 1. Therefore, your first Media
element should always use an Id value of 1.
The Cabinet attribute sets the name of the CAB file. You won't actually see this unless
you set EmbedCab to no, in which case the file will be shipped alongside the MSI. This
is atypical, but might be done to split the installation files onto several disks.
If you do choose to split the installation up into several physical disks (or even
virtual ISO images), you'll want to add the DiskPrompt and VolumeLabel attributes.
In the following example, I've added two Media elements instead of one. I've also
added a Property element above them, which defines a variable called DiskPrompt
with a value of Amazing Software - [1].



[ 22 ]

www.it-ebooks.info

Chapter 1

The Property element will be used as the text in the message box the end user
sees, prompting them to insert the next disk. The text in the DiskPrompt attribute
is combined with the text in the property's value, switched with [1], to change the
message for each subsequent disk. Make sure you give this property an Id value
of DiskPrompt.

So that Windows will know when the correct disk is inserted, the VolumeLabel
attribute must match the "Volume Label" of the actual disk, which you'll set with
whichever CD or DVD burning program you use. Once you've built your project,
include the MSI file and the first CAB file on the first disk. The second CAB file
should then be written to a second disk.
Although we haven't described the File element yet, it's used to add a file to the
installation package. To include one in a specific CAB file, add the DiskId attribute,
set to the Id attribute of the corresponding Media element. The following example
includes a text file called myFile.txt in the media2.cab file:


We'll discuss the File element in more detail later on in the chapter. If you're only
using one Media element, you won't need to specify the DiskId attribute on your
File elements.

The Directory element

So, now we've defined the identity of the product, set up its package properties, and
told the installer to create a CAB file to package up the things that we'll eventually
install. Then, how do you decide where your product will get installed to on the end
user's computer? How do we set the default install path, for example, to some folder
under Program Files?
[ 23 ]

www.it-ebooks.info

Getting Started

When you want to install to C:\Program Files, you can use a sort of shorthand.
There are several directory properties provided by Windows Installer that will be
translated to their true paths at install time. For example, ProgramFilesFolder
usually translates to C:\Program Files. The following is a list of these built-in
directory properties:
Directory property
AdminToolsFolder

Actual path

AppDataFolder

Full path to roaming folder for current user

CommonAppDataFolder

Full path to application data for all users

CommonFiles64Folder

Full path to the 64-bit Common Files folder

CommonFilesFolder

Full path to the Common Files folder for current user

DesktopFolder

Full path to the Desktop folder

FavoritesFolder

Full path to the Favorites folder for current user

FontsFolder

Full path to the Fonts folder

LocalAppDataFolder

Full path to folder containing local (non-roaming)
applications

MyPicturesFolder

Full path to the Pictures folder

NetHoodFolder

Full path to the NetHood folder

PersonalFolder

Full path to the Documents folder for current user

PrintHoodFolder

Full path to the PrintHood folder

ProgramFiles64Folder

Full path to the 64-bit Program Files folder

ProgramFilesFolder

Full path to 32-bit Program Files folder

ProgramMenuFolder

Full path to Program Menu folder

RecentFolder

Full path to Recent folder

SendToFolder

Full path to the SendTo folder for current user

StartMenuFolder

Full path to the Start Menu folder

StartupFolder

Full path to the Startup folder

System16Folder

Full path to the 16-bit system DLLs folder

System64Folder

Full path to the System64 folder

SystemFolder

Full path to the System folder for current user

TempFolder

Full path to the Temp folder

TemplateFolder

Full path to the Template folder for current user

WindowsFolder

Full path to the Windows folder

Full path to directory containing administrative tools

[ 24 ]

www.it-ebooks.info

Chapter 1

This list can also be found at:
http://msdn.microsoft.com/en-us/library/windows/
desktop/aa370905(v=vs.85).aspx

The easiest way to add your own directories is to nest them inside one of the
predefined ones. For example, to create a new directory called Install Practice
inside the Program Files folder, you could add it as a child to ProgramFilesFolder.
To define your directory structure in WiX, use Directory elements:












One thing to know is that you must start your Directory elements hierarchy
with a Directory element with an Id attribute of TARGETDIR and a Name value of
SourceDir. This sets up the "root" directory of your installation. Therefore, be sure
to always create it first and nest all other Directory elements inside.
By default, Windows Installer sets TARGETDIR to the local hard drive with the
most free space—in most cases, the C: drive. However, you can set TARGETDIR
to another drive letter during installation. You might, for example, set it with a
VolumeSelectCombo user interface control. We'll talk about setting properties
and UI controls later in the book.
A Directory element always has an Id attribute that will serve as a primary key on
the Directory table. If you're using a predefined name, such as ProgramFilesFolder,
use that for Id. Otherwise, you can make one up yourself. The previous example
creates a new directory called Install Practice, inside the Program Files folder. Id,
MyProgramDir, is an arbitrary value.

[ 25 ]

www.it-ebooks.info

Getting Started

When creating your own directory, you must provide the Name attribute. This sets
the name of the new folder. Without it, the directory won't be created and any files
that were meant to go inside it will instead be placed in the parent directory—in
this case, Program Files. Note that you do not need to provide a Name attribute for
predefined directories.
You can nest more subdirectories inside your folders by adding more Directory
elements. The following is an example:










Here, a subdirectory called Subdirectory 1 is placed inside the Install Practice
folder. A second subdirectory, called Subdirectory 2, is then placed inside
Subdirectory 1, giving us two levels of nested directories under Install Practice.
If you've been following along using the Visual Studio Setup
Project template, you'll notice that it places its boilerplate
Directory elements inside of a Fragment element. We
will discuss Fragment in the next chapter.

Before jumping into how to add files to your new directories, we should cover the
elements that define the files themselves. The next section covers how to create
components, which are the containers for the files you want to install.

[ 26 ]

www.it-ebooks.info

Chapter 1

The Component element

Once you've mapped out the directories that you want to target or create during the
installation, the next step is to copy files into them. To really explain things, we'll
need something to install. So let's create a simple text file and add it to our project's
directory. We'll call it InstallMe.txt. For our purposes, it doesn't really matter
what's in the text file. We just need something for testing.

Windows Installer expects every file to be wrapped up in a component before
it's installed. It doesn't matter what type of file it is either. Each gets its own
Component element.
Components, which always have a unique GUID, allow Windows to track every
file that gets installed on the end user's computer. During an installation, this
information is stored away in the registry. This lets Windows find every piece of
your product during an uninstall so that your software can be completely removed.
It also uses it to replace missing files during a repair, which you can trigger by
right-clicking on an MSI file and selecting Repair.
Each Component element gets a unique GUID via its Guid attribute. To create a GUID
in Visual Studio, go to Tools | Create GUID and copy a new GUID using the registry
format. The component's Id attribute is up to you. It will serve as the primary key for
the component in the MSI database, so each one must also be unique:




In the preceding code snippet, I've created a new component called
CMP_InstallMeTXT. I've started it with CMP_ to label it as a component, which
is just a convention that I like to use. Although it isn't required, it helps to prefix
components in this way so that it's always clear what sort of element it refers to.
[ 27 ]

www.it-ebooks.info

Getting Started

The File element inside the component references the file that's going to be
installed. Here, it's the InstallMe.txt file located in the current directory (which
is the same directory as your WiX source file). You can specify a relative or absolute
path with the Source attribute.
You should always mark a File element as the KeyPath file and you should only
ever include one File inside a component. A KeyPath file will be replaced if it's
missing when the user triggers a repair (Windows Installer documentation calls this
resiliency). Placing more than one File element inside a single Component element,
at least in most cases, is not recommended. This is because only one file can be the
KeyPath file, so the other files wouldn't be covered by a repair. You would really
only ever place more than one File in a component if you didn't want the extra files
to be resilient.
To add a component to a directory, you have several options. The first, which is the
simplest, is to add your Component elements directly inside the target Directory
element, as given in the following code snippet:










In the previous code snippet, I've instructed the installer to copy the InstallMe.txt
file to the %ProgramFiles%\Install Practice folder that we're creating on the end
user's computer. Although this is the simplest solution, it isn't the cleanest. For one
thing, if you're installing more than a handful of files, the XML file can begin to
look tangled.

[ 28 ]

www.it-ebooks.info

Chapter 1

Another approach is to use a DirectoryRef element to reference your directories.
This has the benefit of keeping the markup that defines your directories independent
from the markup that adds files to those directories. The following is an example:











A third option is to group your components inside of a ComponentGroup and use
its Directory attribute to set the target directory. We will cover component groups
in more detail in the next chapter, but the following snippet will give you an idea:






The File element

As you've seen, the actual files inside components are declared with File elements.
The File elements can represent everything from simple text files to complex DLLs
and executables. Remember, you should only place one file into each component.
The following example would add a file called SomeAssembly.dll to the
installation package:




[ 29 ]

www.it-ebooks.info

Getting Started

A File element should always get the Source attribute. Source defines the path to
the file during compilation. I've listed a relative path here, but you could also specify
an absolute path.
Id, Name, and KeyPath are optional. The Id attribute becomes the primary key for

a row in the MSI database. It should be something unique, but you might consider
starting it with FILE to make it clear that it refers to a File element. If not set, the Id
value will match the filename. Name gives you a chance to change the name of the file
once it's been copied to the end user's computer. By default, it will use the name in
the Source attribute.
To mark a file as important (and that it should be replaced if it goes missing), set it as
the KeyPath file for the component. Since you should only ever place one file inside a
component, in almost all cases that file should be the KeyPath file. If not set, the first
file in the component will be the KeyPath file automatically.
A few other optional but useful attributes for the File element include:
•

Hidden: Set to yes to have the file's Hidden flag set. The file won't be visible

unless the user sets the directory's options to show hidden files.

•

ReadOnly: Set to yes to have the file's Read-only flag set. The user will be

•

Vital: Set to no to continue even if this file isn't installed successfully.

able to read the file, but not modify it unless they change the file's properties.

The Feature element

After you've defined your components and the directories that they'll be copied into,
the next step is to define features. A feature is a group of components that the user
can decide to install all at once. You'll often see these in an installation dialog as a
list of modules, called a feature tree, where each is included or excluded from the
installation. The following is an example of such a tree that has two features – Main
Product and Optional Tools:

[ 30 ]

www.it-ebooks.info

Chapter 1

Every component must be included in a feature. Generally, you should group
together components that rely on one another or that form a complete, self-sufficient
unit. That way, if a feature is disabled, you won't have orphaned files (files that aren't
being used) installed onto the computer. In many instances, if your product doesn't
have any optional parts, you'll only want to create one feature.
If you've included a feature tree dialog (which we'll explain later in the book),
such as the one shown, the user can simply click a feature to exclude it. However,
even without this, they can select features from the command line. The following
command only installs a feature called MainProduct:
msiexec /i myInstaller.msi ADDLOCAL=MainProduct

Here, we're using the msiexec program to launch an installer. The /i flag targets
the MSI file to install. The ADDLOCAL property is set to the names of the features we
want to include. If more than one, use commas to separate the names. To install all
available features set ADDLOCAL=ALL, as shown:
msiexec /i myInstaller.msi ADDLOCAL=ALL

[ 31 ]

www.it-ebooks.info

Getting Started

To create a new feature in your WiX file, add a Feature element inside the
Product element. The following example installs three components under the
feature MainProduct. Another feature called OptionalTools installs another
component. Components are included in a feature with the ComponentRef element.
The Id attribute of ComponentRef targets the Id attribute from the corresponding
Component element:









The Feature element's Id attribute uniquely identifies the feature and is what you'll
reference when using the ADDLOCAL property on the command line. The Title
attribute is used to set a user-friendly name that can be displayed on dialogs. Setting
the Feature element's Level attribute to 1 means that that feature will be included
in the installation by default. The end user will still be able to remove it through the
user interface or via the command line. If, on the other hand, Level is set to 0, that
feature will be removed from the feature tree and the user won't be able to install it.
If you wanted to, you could create a more complex tree with features nested inside
features. You could use this to create more categories for the elements in your product
and give the user more options concerning what gets installed. You would want
to make sure that all possible configurations function correctly. Windows Installer
makes this somewhat manageable in that if a parent feature is excluded, its child
features will be too. The following is an example of a more complex feature setup:




[ 32 ]

www.it-ebooks.info

Chapter 1







In the preceding code snippet, I've moved the ReadMe.txt file used in the previous
examples into its own feature called Documentation that's nested inside the
MainProduct feature. Disabling its parent feature (MainProduct) will also disable it.
However, you could enable MainProduct and disable Documentation.
You have the ability to prevent the user from excluding a particular feature. Just
set the Absent attribute to disallow. You might do this for the main part of your
product where excluding it wouldn't make sense.
You might also consider adding the Description attribute, which can be set to a
string that describes the feature. This could be displayed in your dialog alongside
the feature tree, if you decide to use one. We'll cover feature trees and adding a user
interface later in the book.

Start menu shortcuts

Having a working installer is good, but wouldn't it be nice to add some shortcuts to
the Windows Start menu? First, add another Directory element that references the
Start menu via the built-in ProgramMenuFolder property:









[ 33 ]

www.it-ebooks.info

Getting Started

In the previous code snippet we're adding a new folder to the Start menu called
Awesome Software. Now, we can use a DirectoryRef element to reference our new
shortcuts folder, as in the following code snippet:






Each Shortcut element has a unique identifier set with the Id attribute. The Name
attribute defines the user-friendly name that gets displayed. Description is set to a
string that describes the shortcut and will appear when the user moves their mouse
over the shortcut link.
The Target attribute defines the path on the end user's machine to the actual file
being linked to. For that reason, you'll often want to use properties that update as
they're changed, instead of hardcoded values. In the previous example, the main
installation directory is referenced by placing the Id attribute of its corresponding
Directory element in square brackets, which is then followed by the name of the
file. Even if the path of MyProgramDir changes, it will still lead us to the InstallMe.
txt file.
Two things that should accompany a shortcut are a RemoveFolder element
and a RegistryValue element. RemoveFolder ensures that the new Start menu
subdirectory will be removed during an uninstall. It uses an Id attribute to uniquely
identify a row in the MSI RemoveFile table and an On attribute to specify when to
remove the folder. You can set On to install, uninstall, or both. You can specify
a Directory attribute as well to set to the Id attribute of a Directory element to
remove. Without one, though, the element will remove the directory defined by the
parent DirectoryRef or ComponentGroup element.

[ 34 ]

www.it-ebooks.info

Chapter 1

The RegistryValue element is needed simply because every component must
have a KeyPath item. Shortcuts aren't allowed to be KeyPath items as they aren't
technically files. By adding a RegistryValue, a new item is added to the registry
and this is marked as KeyPath. The actual value itself serves no other purpose. We
will cover writing to the registry in more detail later.








There's actually another reason for using a RegistryValue element as KeyPath. The
shortcut we're creating is being installed to a directory specific to the current user.
Windows Installer requires that you always use a registry value as the KeyPath item
when doing this in order to simplify uninstalling the product when multiple users
have installed it.
Another type of shortcut to add is one that uninstalls the product. For this, add a
second Shortcut element to the same component. This shortcut will be different
in that it will have its Target set to the msiexec.exe program, which is located in
the System folder. The following example uses the predefined System64Folder
directory name because it will automatically map to either the 64-bit or 32-bit System
folder, depending on the end user's operating system.

[ 35 ]

www.it-ebooks.info

Getting Started

By setting Target to the path of an executable, you're telling Windows to launch
that program when the user clicks the shortcut. The msiexec program can remove
software by using the /x argument followed by the ProductCode attribute of
the product you want to uninstall. The ProductCode attribute is the Id attribute
specified in the Product element.









Notice that we don't have to use the GUID from the Product element to get
the ProductCode value. We can reference it using the built-in property called
ProductCode surrounded by square brackets. If you'd like to add an icon to your
shortcut, first add an Icon element as another child to the Product element. Then,
reference that icon with the Icon attribute on the Shortcut element, as shown in the
following code snippet:









Be sure to add the new component that contains the shortcuts to one of your features:





Putting it all together

Now that you've seen the different elements used to author an MSI package, the
following is the entire .wxs file:






[ 37 ]

www.it-ebooks.info

Getting Started































Compile the project in Visual Studio and you should get a new MSI file:

[ 39 ]

www.it-ebooks.info

Getting Started

You can double-click on it or right-click and select Install to install the software.
Doing so should create a subfolder for your program in the Start menu, as shown
in the following screenshot:

You should also find a new folder under Program Files:

To uninstall the software, you have several options:
•

Use the uninstall shortcut from the Start menu

•

Right-click on the MSI file and select Uninstall

•

Uninstall it from Programs and Features

•

From a command prompt, navigate to the directory where the MSI file is and
use the following command:
msiexec /x AwesomeSoftware.msi

Adding a user interface

Although you'll eventually want to add your own dialogs to gather information from
the user that's important for your own application, you may want to use one of WiX's
built-in dialog sequences in the meantime. All of them are stored in an assembly called
WixUIExtension.dll. You can add a reference to this file with Visual Studio's Add
a Reference screen. The file exists in WiX's Program Files folder. You may have to
navigate to C:\Program Files (x86)\WiX Toolset v3.6\bin.

[ 40 ]

www.it-ebooks.info

Chapter 1

Once you've added the new reference, add the following line to your WiX source file.
It doesn't matter exactly where, as long as it's a child to the Product element:


This will insert the Minimal dialog set into your installation sequence. It shows a
single dialog screen containing a license agreement and an Install button. Feel free
to try any of the other dialog sets. Just replace WixUI_Minimal, with one of the other
names in the UIRef element. WixUI_Advanced and WixUI_InstallDir require some
further setup to really work properly. You can try out the following attributes:
•

WixUI_Advanced

•

WixUI_FeatureTree

•

WixUI_InstallDir

•

WixUI_Mondo

We will explore these standard dialogs in more detail later and also explain how to
create your own.

Viewing the MSI database

I mentioned before that an MSI file is really a sort of relational database. WiX does
all the work of creating tables, inserting rows, and matching up keys in this database.
However, as we progress through the rest of the book, I encourage you to explore
how it looks behind the scenes. For example, we discussed the File and Component
elements. Sure enough, there are two tables called File and Component in the MSI
package that contain the definitions you've set with your XML markup. To get inside
the installer, you'll need a tool called Orca.

Orca.exe

Once you've compiled your project in Visual Studio, you'll have a working MSI
package that can be installed by double-clicking on it. If you'd like to see the
database inside, install the MSI viewer, Orca.exe. Orca is provided as part of
the Windows SDK and despite the icon of a whale on the shortcut, it stands for
One Really Cool App. You can find versions of the SDK at Microsoft's Windows
Development Center website:
http://msdn.microsoft.com/en-us/windows/bb980924.aspx

[ 41 ]

www.it-ebooks.info

Getting Started

After you've installed the SDK (specifically, the .NET tools that are included), you
can find the installer for Orca—Orca.msi—in the Microsoft SDKs folder in Program
Files. On my machine, it can be found in C:\Program Files\Microsoft SDKs\
Windows\v7.0\Bin.
Install Orca and then right-click on your MSI file and select Edit with Orca, as shown
in the following screenshot:

Orca lets you view the database structure of your installer. This can be a big help in
troubleshooting problems or just to get a better idea about how different elements
work together. The following is a screenshot of the Component database:

If you wanted to, you could edit your MSI package directly with Orca. This is helpful
when learning or trying out different concepts. You'll need to know exactly which
tables and rows to modify. Sometimes, though, you'll be able to just change a single
value and check its effect.

Turning logging on during installation

If you get into trouble with your installer, it may help to run it with logging turned
on. To do so, install your package from a command prompt using msiexec with the
arguments /l*v, and the name of a file to write the log to. For example, if you had an
installer called myInstaller.msi, you could use this command to write a log during
the installation to a file called myLog.txt:
msiexec /i myInstaller.msi /l*v myLog.txt
[ 42 ]

www.it-ebooks.info

Chapter 1

Every event that occurs during installation will be recorded here. It works for
uninstalls too. Simply use the /x argument instead of /i. The log can be pretty
helpful, but also very verbose. If your installer fails midway through, you might try
searching the log for the text return value 3. This indicates that an action returned
a status of failure. Often, you'll also see a specific MSI error code. You can find its
meaning by searching for that number in the MSI SDK Documentation help file
that comes with WiX.
You can also turn on logging for all MSI packages by editing the
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\
Windows\Installer key in the Windows Registry. This should
be used with care though so as not to use too much disk space.
See http://support.microsoft.com/kb/223300 for more
information.

Other resources

If you have specific questions about WiX, you'll find additional resources at the
following websites:
•

WiX users mailing list:
http://sourceforge.net/mailarchive/forum.php?forum_name=wixusers

•

Microsoft Windows Installer documentation:
http://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx

Summary

In this chapter, we discussed downloading the WiX toolset and its various features.
Creating a simple MSI package is relatively easy. There are only a handful of XML
elements needed to get started. As we explore more complex setups, you'll be
introduced to elements that are more specialized.
Throughout the rest of this book, I'll make references to the structure of the MSI
database. Orca is an excellent tool for seeing this structure yourself. Although this
book focuses on WiX and not the underlying Windows Installer technology, it helps
sometimes to see how the mechanics of it work. You may find it useful to consult
Microsoft's MSI documentation too, which can be found online or in a help file
provided by WiX, to get a deeper understanding of the properties and constructs
we will discuss.
[ 43 ]

www.it-ebooks.info

www.it-ebooks.info

Creating Files and Directories
In the previous chapter, we saw that creating a WiX installer isn't so tough. Less
than seventy lines of code and you've got a professional-looking deployment solution.
One of the things we covered was how to copy files and create directories on the end
user's computer. We've covered the basics, but now it's time to dig deeper.
In this chapter you will learn how to:
•

Organize your File and Directory elements using the DirectoryRef and
ComponentGroup elements

•

Split your WiX markup using Fragment elements to keep it manageable

•

Use heat.exe to create the Component markup

•

Install special case files such as installing to the GAC

The File element

The File element, as you've seen, is used to designate each file that you plan to copy
to the end user's computer. At a minimum, it should contain a Source attribute that
identifies the path to the file on your development machine, as shown:




www.it-ebooks.info

Creating Files and Directories

There are a number of optional attributes available. The Name attribute tells the
installer what the file will be called after it's installed. If omitted, the file will retain
its original name as specified in the Source attribute. The KeyPath attribute explicitly
marks the file as the keypath for the component, although if there is only one File
element in Component it will, by default, be the keypath. The Id attribute uniquely
identifies the file in the MSI database's File table. The following is an example that
demonstrates these attributes:







This example includes two files, MyProgram.exe and AnotherFile.dll, in the
installation package. Both use relative paths for their Source attributes. The first file
is located in the current directory while the second is two directories up. Another
option is to use a preprocessor variable to store the location of your files.

[ 46 ]

www.it-ebooks.info

Chapter 2

Preprocessor variables are evaluated at compile time and are replaced in the final
MSI file with the strings that they've been set to. Here, I've added a variable called
FilesPath on the Build page of my WiX project's Properties page, and set it to
..\..\myProgram\Output\. In this case, the Output directory is where the files I
plan to install are located on my computer. We can insert this variable in the markup
by using $(var.FilesPath), as in the following snippet:




At compile time, the variable will be replaced with the path that we've defined. You
can define more than one preprocessor variable on the Build page by separating
them with semicolons.
You can also refer to other projects in your Visual Studio solution using preprocessor
variables. For example, let's say you had a class library project in the same solution
as your WiX setup. If you were to add that class library as a reference in the WiX
project, you could then refer to its output directory using $(var.ProjectName.
TargetDir), as in the following example:




Here, after we've added a project reference to the MyAssembly project, we are able to
reference its output directory via the $(var.MyAssembly.TargetDir) variable. You
can see other variables that are made available when adding a project reference in
this way at:
http://wix.sourceforge.net/manual-wix3/votive_project_references.htm

A File element is always wrapped in its own Component element. Doing so will
allow you to mark every file that you're installing as a KeyPath file. This allows
them to be replaced if they're accidentally deleted. The process of replacing missing
files is known as a repair. Repairs are triggered by right-clicking on an MSI file and
selecting Repair. A component can have only one keypath file, but every component
should have one. Although it's possible to put more than one file in the same
component, it's considered bad practice.

[ 47 ]

www.it-ebooks.info

Creating Files and Directories

Before moving on, two other helpful attributes on the File element are Hidden and
ReadOnly. Setting the first to yes causes the installed file to be hidden from view.
The second turns on the file's read-only flag.

The DirectoryRef element

In the previous chapter, you saw that to define which directories to copy your files
into, you use Directory elements. These take an Id value and, if it's a new directory
that you're creating, a Name attribute. You can use any of the built-in IDs to reference
one of the common Windows directories. For example, suppose we wanted to add
an XML configuration file for our software to the %PROGRAMDATA% folder. We'd add a
reference to it using the built-in CommonAppDataFolder property as Directory Id:






Here we are placing a new folder called Awesome Software inside the %PROGRAMDATA%
folder. The new folder gets a Name attribute to label it. The Id attribute is up to us and
uniquely identifies the directory in the MSI database. To add a file to our directory we
add a new DirectoryRef, as shown in the following code snippet:






The DirectoryRef element matches the Directory element that we used before.
If you wanted to, you could use a new DirectoryRef element for each file.
However, it's easier to use one DirectoryRef and place multiple Component
elements inside of it:





[ 48 ]

www.it-ebooks.info

Chapter 2




You could, for example, place hundreds of files inside the MyCommonAppDataFolder
directory using only one DirectoryRef element.

The ComponentGroup element

The ComponentGroup element is used to group Component elements, which is
helpful as it offers a way to reference all of your components with a single element.
For example, when adding components to Feature (which you must always do),
you could use ComponentRef elements directly. This is the technique we used in the
previous chapter:





However, by creating ComponentGroup, you can reference multiple components with
a single ComponentGroupRef element. This is shown in the following snippet:




Try it out by adding a new CompontGroup element to your .wxs file. It can go
anywhere inside the Product element. Then, you have a choice. You can either nest
Component elements inside it or use ComponentRefs to reference your components
indirectly. For example, here we use Component elements inside ComponentGroup:




[ 49 ]

www.it-ebooks.info

Creating Files and Directories






Since the components aren't wrapped in a DirectoryRef element anymore, we're
adding Directory attributes to the Component elements to set the target directory.
This has the same effect though. It will tell the installer where to copy these files
to. You can also put a Directory attribute on the ComponentGroup element itself,
setting the target directory for all child components:





The other option is to continue to nest Component elements inside the DirectoryRef
elements and then use the ComponentRef elements to include them in a group:












[ 50 ]

www.it-ebooks.info

Chapter 2

The usefulness of ComponentGroup becomes more obvious when your program
needs to copy more than a few files to the end user's machine. You'll be able to
include, remove, or move entire sets of components from a feature simply by
moving the ComponentGroupRef element.

The Fragment element

Up to this point, we've been adding all of our WiX elements to the Product.wxs
file. When your installer packages hundreds of files, you'll find that having all of
your code in one place makes reading it difficult. You can split your elements up
into multiple .wxs files for better organization and readability. Whereas your main
source file, Product.wxs, nests everything inside a Product element, your additional
.wxs files will use Fragment elements as their roots.
The Fragment element doesn't need any attributes. It's simply a container. You can
place just about anything inside of it, such as all of your Directory elements or all
of your Component elements. For the next example, add a new WiX source file to
your project and place the following markup inside it. Here, we're using the same
ComponentGroup that we discussed earlier. You can call the file Components.wxs,
and it should look something like the following code snippet:














[ 51 ]

www.it-ebooks.info

Creating Files and Directories

Now, the markup for the components is contained within a separate file. We've used
ComponentGroup to group them, but of course, that's optional. To include this group
in Product.wxs, reference it with a ComponentGroupRef element in one of your
Feature elements, as shown:




Although the ComponentGroup element is optional, it allows us to reference our
fragment back in our main source file. Referencing any single element from a
fragment like this will pull all of the elements in the fragment into the scope of your
project. For components, this doesn't make much difference since you still have
to reference all of them—or at least a ComponentGroup element of them—inside a
Feature element. However, it makes more of a difference for other elements.
For example, properties, which are variables that you can use to store data, are
represented by Property elements and could be stored in a separate file within
a Fragment element. Then, by referencing just one of them in your main source
file with a PropertyRef element, you'd pull all of them into your project. With
fragments, it's all or nothing. Referencing one element in the fragment references
them all.
Other elements that don't have a corresponding Ref counterpart need a little more
help. For example, there's no reference element for the Media element. There's no
such thing as a "MediaRef". However, if you included a Property element in the
same fragment as your Media elements, you could pull them in too by referencing
that property with PropertyRef. The Media.wxs file would look like the following
code snippet:










[ 52 ]

www.it-ebooks.info

Chapter 2

To reference the Media elements in your project, reference the property that's with
them. This is done by adding the following code to Product.wxs:





















[ 53 ]

www.it-ebooks.info

Creating Files and Directories

Fragments are a great way of splitting up your code to make it more manageable.
As we've seen, it's easy to pull them into the scope of your project. You could even
pull one fragment into another and then pull that one into your main source file.
WiX will take care of running the validity checks to make sure that everything links
together properly.
Note that it's possible to have more than one Fragment element in the same source
file. In that case, you must use a reference element for each one. They're sort of like
islands. They're isolated from one another. However, it's often simpler to stick to one
fragment per file. The following file defines two fragments:












Referencing the MediaProperty property with PropertyRef will only pull in the
elements in the first fragment. To get those in the second fragment, you'd have to
also reference the MediaProperty2 property.
The Fragment element is so helpful that the WiX team has employed its use for an
even bigger type of project organization: .wixlib files. These are separate projects
that by default contain a single fragment and compile into a WiX library (.wixlib)
that can be added as a reference in your main WiX project. This allows other teams to
handle their own WiX code and send it to you already compiled. To try it out, create
a new project in your solution using the Setup Library Project template.

[ 54 ]

www.it-ebooks.info

Chapter 2

The contents of this type of project aren't anything you haven't seen before. It's
simply a fragment. You'll start off with the following markup:







You can add properties, components, and anything else you'd ordinarily be able to
add to a fragment. When it's compiled, you'll have a .wixlib file that can be added as
a reference in your main WiX project. Use the Add Reference option in your Solution
Explorer window. Like other fragments, you'll be able to reference the .wixlib file's
contents by using a reference element such as PropertyRef. This is a great tool that
allows multiple teams to work on the installer without stepping on one another's toes.
In the past, installation developers often used merge modules (.msm) to separate
installation code. Merge modules, much like WiX libraries, contain compiled installer
code and offer a way of splitting up large projects. WiX libraries, which are easier to
author, can serve as a replacement for merge modules.
WiX does provide an XML element called Merge for importing a merge module
into your project. You'd probably only need to use this to install a third-party
component. However, even for dependencies such as Microsoft's Visual C++
Runtime, you may be able to avoid using a merge module and use an executable
installer instead. An installer for the Visual C++ Runtime is available and by using
WiX's new bootstrapper technology, Burn, it can be installed as a prerequisite before
your own software is installed. We'll cover Burn later in the book.

Harvesting files with heat.exe

When your project contains many files to install, it can be a chore to create File and
Component elements for all of them. Instead, WiX can do it for you. One of the tools
that ships with the toolset is called heat.exe. You can find it in the bin directory of
the WiX program files. Navigate to WiX's bin directory from a command prompt
and type heat.exe -? to see information about its usage.
[ 55 ]

www.it-ebooks.info

Creating Files and Directories

To make things easy, consider adding the path to the WiX bin directory to your
computer's PATH environment variable so that you won't have to reference the
full path to the executable each time you use it. You can do this on Windows 7 by
right-clicking on My Computer in your Start Menu and then going to Properties |
Advanced system settings | Environment Variables. From there, you can add the
WiX bin path, C:\Program Files (x86)\WiX Toolset v3.6\bin, to PATH by
finding PATH in the list of system variables and clicking on Edit.
Note that WiX, during its installation, adds an environment
variable called WIX, but this references the bin folder's
parent directory. You could add %WIX%bin to PATH.

The following is the general syntax for Heat:
heat.exe harvestType harvestSource 
-o[ut] sourceFile.wxs

Heat can look at a directory, evaluate all of the files in it, and create a .wxs file
defining the components you'd need to install all of those files. First, let's create a
new directory and then add some empty text files in it. You can create it anywhere
you like.

Open a command prompt and navigate to this directory. I'll assume that the WiX bin
directory has been added to your PATH environment variable and won't reference
the full path to heat.exe. The first argument that you have to give to Heat is a
harvestType, which can be one of the following:
•

dir: This type harvests a directory

•

file: This type harvests a file

•

payload: This type harvests a bundle payload as RemotePayload

•

perf: This type harvests performance counters

[ 56 ]

www.it-ebooks.info

Chapter 2

•

project: This type harvests output of a VS project

•

reg: This type harvest a .reg file

•

website: This type harvests an IIS website

We'll be harvesting all the files from the directory we've created, so we'll use dir.
The second argument is the path to the directory. It can be a relative or absolute
path and should not end in a backslash. I'll truncate it in this example for the sake
of clarity. The last argument, which is preceded by the -out flag, is the name of a
source file that Heat will create. So, our Heat command looks like this so far:
heat.exe dir "C:\Testing_Heat" -out ".\HeatFile.wxs"

We've asked it to create a file called HeatFile.wxs in the current directory. The
following is what it would contain:




















[ 57 ]

www.it-ebooks.info

Creating Files and Directories










It created WiX markup for us. However, things aren't quite as good as they could
be. For one thing, it has created a Directory element with a Name attribute of
Testing_Heat, the same as my impromptu folder. This will create a directory
called Testing_Heat on the end user's computer. That's not what I wanted. Also,
it has set the Guid attribute on each Component to PUT-GUID-HERE. Although this
could be useful in some circumstances, I'd much rather it created the GUIDs for me.
It has also set the Source attribute on each File element to SourceDir\FILENAME.
This means that when we build the project, the compiler will expect to find the text
files in the same directory where the HeatFile.wxs file is. Finally, it hasn't made it
easy for us to reference the components that it created. It would have been nice to see
all of these components grouped into a ComponentGroup element.
To fix these problems, we'll just add some more arguments to our call to Heat,
as outlined in the following table:
Argument

What it does

-cg 

Add the -cg flag with a name to use for a new
ComponentGroup element. Heat will then group the
components.

-dr 

Use the -dr flag with the name of one of the directories you
actually wanted to create. That way, the components will be
copied into that directory during the installation.

-gg

To have Heat create GUIDs for us, add the -gg flag.

-g1

To have the GUIDs not have curly brackets, use the -g1 flag.
This is just a preference.

-sfrag

By default, Heat puts each component and your directory
structure in separate Fragment elements. Adding -sfrag
puts these elements into the same Fragment element.
[ 58 ]

www.it-ebooks.info

Chapter 2

Argument
-srd

What it does

-var 

We can use the -var flag with the name of a preprocessor
variable (preceded by var) to insert in place of SourceDir.
Later on, we can set the variable from within the project's
Properties settings or on the command line.

There's not really any reason to harvest the folder where the
files are, so add the -srd flag.

Now, our call to Heat will look something like the following command:
heat.exe dir "C:\New Folder" -dr MyProgramDir -cg NewFilesGroup
-gg -g1 -sf -srd -var "var.MyDir" -out ".\HeatFile.wxs"

The new HeatFile.wxs looks like the following code snippet:




















[ 59 ]

www.it-ebooks.info

Creating Files and Directories

This looks a lot better. Now, the components are grouped, each Component has a
GUID and is being installed into the MyProgramDir folder that I'm creating, and the
File elements are using the $(var.MyDir) variable in their Source attributes. To
include these new components in Product.wxs, add a reference to ComponentGroup
with a ComponentGroupRef element inside one of the features:





Also, be sure to add a value for the MyDir variable. Here, we set it to a folder named
SomeFolder in our project's directory (assuming we move our text files there before
compiling the project):

After you've compiled the project, you can use Orca to look at the MSI data that this
produces. The Component table will show the new components and the File table
will show the new files:

Remember that every time you run Heat on a directory, and you've set the -gg flag,
it will create new GUIDs for your components. If you've already shipped a version
of your software to customers, then these GUIDs should not be changed. To do so
would prevent Windows from accurately keeping track of them. Heat will also create
new Id attributes for File and Component elements each time you use it. This is just
something to keep in mind, especially if other parts of your installer expect the Id
attribute to stay the same from one day to the next.
[ 60 ]

www.it-ebooks.info

Chapter 2

Copying and moving files

File and Component elements allow you to add new files to the end user's computer.

However, WiX also provides ways to copy and move files. For these tasks, you'll use
the CopyFile element. We'll discuss how to use it in the following sections.

Copying files you install

The CopyFile element can copy a file that you're installing and place it in another
directory. You'll nest it inside the File element of the file you want to duplicate.
First, we'll add a subdirectory to the MyProgramDir folder that we're already creating
under Program Files. The new directory will be called Copied Files.








Now, we can nest a CopyFile element inside the File element of the file we want to
copy. Here, we're copying the InstallMe.txt file to the Copied Files folder and
renaming it to InstallMeCOPY.txt. Notice that we use the DestinationDirectory
attribute to specify the Id attribute of the Copied Files directory. We use the
DestinationName attribute to specify the new filename. Every CopyFile element
has to have a unique ID, so we set that too:








[ 61 ]

www.it-ebooks.info

Creating Files and Directories

That's all you need. During installation, the InstallMe.txt file will be copied to the
Copied Files folder and named InstallMeCOPY.txt. If you wanted to, you could
nest multiple CopyFile elements under the same File element and copy that file to
several places. Just be sure to give each CopyFile element a unique ID.
If you don't want to hardcode the destination directory, you can use the
DestinationProperty attribute instead of DestinationDirectory to reference a
directory at install time. DestinationProperty accepts the name of a property that's
set to a directory path. The following is an example:









So here we've hardcoded the path again. It's just that this time we used a property to
do it instead of a Directory element. The DestinationProperty attribute is most
useful when you can set the property dynamically. There are various ways that you
can do this:
•

Ask the user for it on a UI dialog and then set the property with the result.
We'll talk about setting properties from dialogs later in the book.

•

Set the property from a custom action. This is something else we'll
cover later. The action that you create must be executed before the
DuplicateFiles action in InstallExecuteSequence.

•

Set the property from the command line. We'll cover this in the next chapter.

•

Use AppSearch, which we'll cover, to find the directory you want and set the
property with it.

[ 62 ]

www.it-ebooks.info

Chapter 2

Copying existing files

In addition to being able to copy files that you're installing, you can also copy files
that already exist on the end user's computer. For this, you'll nest the CopyFile
element inside its own Component element and not inside a File element. The
following is an example that copies a file called TEST.txt that's on the desktop
to a folder called Copied Files:
















We've added a Directory element to reference the Desktop folder so that we
can reference it later in the CopyFile element. The Component element that holds
the CopyFile has its KeyPath attribute set to yes. We did this because we're not
installing anything with this component and something has to be the keypath. In
cases such as this, when there's nothing else to serve the purpose, it's fine to mark the
component itself as the KeyPath file.

[ 63 ]

www.it-ebooks.info

Creating Files and Directories

The CopyFile element here has the DestinationDirectory and DestinationName
attributes like before, but it also has the SourceDirectory and SourceName
attributes. SourceDirectory is set to the Id attribute of a Directory element where
the file you want to copy is. SourceName is the name of the file you want to copy.
If you wanted to, you could use the DestinationProperty attribute instead of
DestinationDirectory, and SourceProperty instead of SourceDirectory. These
are used to set the directory paths at installation time, as discussed before.

Moving existing files

Suppose you didn't want to copy a file that already existed, but rather move it to
some other folder. All you need to do is add the Delete attribute to your CopyFile
element. This will delete the file from its current location and copy it to the new
location. So, that's another way of saying "move". The following is an example:






Unfortunately, when you uninstall the software, it doesn't move the file back. It just
removes it completely from its current location.

Installing special-case files

In the following sections, we'll take a look at installing files that are different from
other types that we've talked about so far. Specifically, we'll cover how to install an
assembly file (.dll) to the Global Assembly Cache and how to install a TrueType
font file.

[ 64 ]

www.it-ebooks.info

Chapter 2

Adding assembly files to the GAC

The Global Assembly Cache (GAC) is a central repository in Windows where you
can store .NET assembly files so that they can be shared by multiple applications.
You can add a .NET assembly to it with WiX by setting the File element's Assembly
attribute to .net. The following example installs an assembly file to the GAC:






Even though we've placed this component inside a DirectoryRef element, that
references the MyProgramDir directory, it won't really be copied there since we're
installing it to the GAC. Another approach is to create a dummy folder called GAC
that's used solely for this purpose. In that case, you wouldn't give that Directory a
Name attribute, which would prevent it from truly being created.
I'm using an assembly called MyAssembly.dll in this example, that I created with a
separate Visual Studio project. Any DLL that you want to install to the GAC must
be strongly signed. You can do this by opening the Properties page for that project
in Visual Studio, viewing the Signing page, checking the box that says Sign the
assembly, and creating a new .snk file, as shown in the following screenshot:

[ 65 ]

www.it-ebooks.info

Creating Files and Directories

Once you've installed the package that now contains the strongly-signed assembly,
you'll be able to check if the DLL file actually made it into the GAC. Navigate to the
GAC assembly folder to see a list of installed assemblies:

Assemblies that target the .NET 4 Framework will use the
new GAC folders under C:\Windows\Microsoft.NET\
assembly. Assemblies targeting an earlier framework will be
placed in C:\Windows\assembly.

The nice thing is that when the user uninstalls the software the assembly will be
removed from the GAC—that is, unless another software product is still using it.
Windows keeps a count of products using each assembly and deletes your .dll only
when the count reaches zero.

Installing a TrueType font

To install a TrueType font onto the system, set the File element's Source attribute
to the location of a TTF file on your build machine and the TrueType attribute to
yes. The File element is nested inside a Component element that targets the built-in
FontsFolder directory. In the following example, we add a Directory element with
an Id value of FontsFolder and reference it with DirectoryRef:






[ 66 ]

www.it-ebooks.info

Chapter 2







In the preceding code snippet, the File element is using the TrueType attribute to
signify that this file is a font file. It will include myFont.TTF from the current build
directory, in the install package and copy it to the end user's C:\WINDOWS\Fonts
folder.

Installing 64-bit files

Let's say that you have a .NET assembly that's targeting the x64 platform and
you want the installer for it to place that file into the 64-bit Program Files folder
(available on 64-bit Windows operating systems). For the uninitiated: you can set the
platform for the assembly using Visual Studio's Configuration Manager, as shown in
the following screenshot:

[ 67 ]

www.it-ebooks.info

Creating Files and Directories

The first thing to do is to open Properties for the WiX project and, on the Tools
Settings tab, add –arch x64 to the Compiler parameters, as shown in the
following screenshot:

Next, change the Directory element that is referencing ProgramFilesFolder to
instead reference ProgramFiles64Folder, given as follows:






Now your 64-bit assembly can be put into this directory. WiX detects the architecture
of the .NET assemblies for you. You'll get a compile-time error if you try to put a 64bit file into a 32-bit folder, or vice versa.

[ 68 ]

www.it-ebooks.info

Chapter 2

Creating an empty folder

Ordinarily, Windows Installer won't let you create empty folders. However, there
is a way: Use the CreateFolder element inside an otherwise empty Component
element. First, you'll define the name of your empty directory with a Directory
element. Follow this example:








In the example, we've added a new Directory element named Empty Directory
inside our main application folder. The next step is to add a component to this
directory by using a DirectoryRef element. Notice that we've set the KeyPath
attribute on the component to yes, as there will be no file to serve this purpose:






The only thing inside the component is a CreateFolder element. This tells Windows
Installer that the folder will be empty, but that it should still create it during the
install. As always, be sure to add this new component to a feature, as given in the
following code snippet:





[ 69 ]

www.it-ebooks.info

Creating Files and Directories

Setting file permissions

WiX allows you to set the permissions that Windows users and groups have to the
files that you install. You can see these permissions by right-clicking on a file and
selecting the Security tab. On Windows XP, you may have to configure your system
so that this tab is visible. In Windows Explorer, open the folder that you want to
configure and go to Tools | Folder Options | View. Then, uncheck the box that says
Use simple file sharing. The following is an example of the Security tab on a file:

[ 70 ]

www.it-ebooks.info

Chapter 2

To set the permissions for a file that you're installing, nest a PermissionEx element
inside the corresponding File element. This element, which is available from
WixUtilExtension, has various attributes that can be used to define file permissions.
Before you can use it, you'll need to add a reference to WixUtilExtension.dll in your
project. Go to Add Reference in Solution Explorer and select the WiXUtilExtension
assembly. Next, add the following namespace to your Wix element:


The following attributes are available to the PermissionEx element. Each can be set
to either yes or no:
Attribute
GenericAll

What it does

GenericRead

Must have at least one other permission specified. Grants all
Read privileges: "Read Data", "Read Attributes", "Read Extended
Attributes", and "Read Permissions".

GenericWrite

Grants "Write Data, "Append Data", "Write Attributes", and "Read
Permissions".

GenericExecute

Grants "Execute File", "Read Attributes", and "Read Permissions".

Read

Grants "Read Data".

Write

Grants "Write Data".

Execute

Grants "Execute File" permission.

Append

Grants "Append Data".

Delete

Grants "Delete".

ChangePermission

Grants "Change Permissions".

ReadPermission

Grants "Read Permissions".

TakeOwnership

Grants "Take Ownership".

Synchronize

If "yes", then threads must wait their turn before accessing the file.

Gives the user all permissions.

The following example references the util namespace from the Wix element and uses
its PermissionEx element to set file permissions on the InstallMe.txt file. Notice
that I'm also using another element from WixUtilExtension called User. This can
be used to create a new Windows user on the target computer. The Product.wxs file
would look something like the following code content:






















[ 72 ]

www.it-ebooks.info

Chapter 2








In this example, we've given all privileges to the user we just created, nickramirez.
You can see all of the users for a computer by going to your Start Menu, right-clicking
on Computer, selecting Manage, and viewing the Local Users and Groups node. The
PermissionEx element's GenericAll attribute gives the user all possible privileges.
Just so you know, any users that you create during an installation will be removed
during an uninstallation if you set the User element's RemoveOnUninstall attribute
to yes.

[ 73 ]

www.it-ebooks.info

Creating Files and Directories

Speeding up file installations

We haven't talked too much about how the files and directories that you author in your
WiX source files are stored in the MSI database's tables. The files are stored in a table
called File, the directories in a table called Directory, and the components in a table
called Component. You can see this by opening the MSI package with Orca.exe.
In the following example, I have four files that are being installed. I've used the
convention of prefixing my file IDs with FILE_, giving me FILE_InstallMeTXT,
for example:

Each file in the File table is sorted alphabetically by the Id value you gave to it via
the File element. This is the order in which the files are copied to the end user's
computer. So, how can you make things faster? You can give your files IDs that will
cause WiX to sort them more efficiently.
The file copy process takes longer when Windows has to write to one directory and
then switch to another and then another and so on. If it could copy all of the files that
belong to a certain directory at the same time and then move to another location, the
process would be more efficient. As it is, Windows may leave and return to the same
directory several times as it goes through the alphabetical list.
To speed things up, we should add the name of the directory where the file is set to go
to the Id attribute of the file. To be effective, this should come at the beginning of Id.
That way, files going to the same place will appear next to each other in the list. So, in
addition to prefixing our file IDs with FILE_, we could also indicate the directory that
each is being copied to. For example, FILE_MyProgramDir_InstallMeTXT signifies
that this file is being copied to the MyProgramDir directory. Any other files being
copied to the same place should also get MyProgramDir in their IDs.

[ 74 ]

www.it-ebooks.info

Chapter 2

The following example displays a list that is better organized. It uses the name of
the destination directory as part of the files' IDs. Files going to the same place will be
grouped together in the alphabetical list, as shown in the following screenshot:

I've used underscores to separate the prefixes, but it's also common to use periods.
So, I could have named the first file FILE.MyProgramDir.InstallMe.Txt instead of
FILE_MyProgramDir_InstallMeTXT. It's really just a matter of preference.

Summary

In this chapter, we discussed the elements used to install files and create directories.
The File, Directory, and Component elements play vital roles here, but you may also
benefit from using ComponentGroup to group your components. This allows you to
better organize your markup and even to separate it into multiple WiX source files.
The heat.exe tool can create Component elements for you. You simply need to
point it at a certain directory. However, it's best to fine-tune its arguments so that
the output that you get is optimal. We discussed a few other topics such as how to
copy a file, how to set file permissions, and how to organize your File element Id
attributes for maximum installation speed.
In the next chapter, we'll move on to discuss WiX properties and the various ways of
searching the end user's system for files, directories, and settings.

[ 75 ]

www.it-ebooks.info

www.it-ebooks.info

Putting Properties and
AppSearch to Work
When using WiX, properties are the variables that store any temporary data during
an install. As such, they provide definitions for various predefined and custom-made
installer settings, store input from the user, and provide a means of transferring
information from one task to another. Additionally, they can store the results of
searching the user's computer for files, directories, registry keys, and settings.
In this chapter, you will learn:
•

The syntax for declaring and setting properties

•

How to reference properties in other parts of your markup

•

The built-in properties that Windows Installer sets for you

•

What AppSearch is and how to use it to search the end user's computer for
installed components, registry keys, and so on

Custom properties

You'll often need to define and set custom properties to hold your install time data.
In the following sections, we will explore the meaning of WiX properties and how
best to use them. I should say that properties are not just a feature of WiX, but are
innate to Windows Installer itself. So, additional information about them can be
found in the Windows Installer documentation.

www.it-ebooks.info

Putting Properties and AppSearch to Work

Declaring and setting properties

To declare a property, add a Property element to your WiX markup. A Property
element only needs two attributes: Id and Value. The Id attribute sets the name of
the property, and the Value attribute sets the data contained inside. The following
example creates a new property called myProperty and sets its value to the string
my value. Note that this can go anywhere inside the Product element.


Id should begin with either a letter or underscore and consist of only lower and
uppercase letters, numbers, underscores, and periods. When referencing it, it's case
sensitive. So, MyPropertyId is not the same as MyPropertyID.

The data in Value can be almost any string. If you need to use double quotes in the
value, you can either surround it with single quotes, as in the following example:


Or you can use the XML entity " in place of the double quotes:


If you omit the Value attribute, the property will be set to null. During compilation,
properties with null values are left out of the MSI package. It will be as if you hadn't
declared them at all.
You can also set the value of a Property element by adding inner text to it, as in the
following example:
my value

Properties can also be set from the command line. If you do, you're not required to
declare the property in your WiX markup first. Declaring them on the command line
creates them dynamically. When defining properties on the command line, their IDs
must be uppercase. This is to make them "public", which we'll discuss later in the
chapter. To add a property in this way, add the name and value of your property,
separated by an equals sign, after the msiexec command.
msiexec /i myInstaller.msi PROPERTY1=100 PROPERTY2="my value"

[ 78 ]

www.it-ebooks.info

Chapter 3

Here we're declaring two properties at install time, PROPERTY1 and PROPERTY2, and
setting their respective values. You can add more than one property by separating
them with spaces, as we've done here. Literal string values that have spaces in them
should be surrounded by double quotes. If the value itself has double quotes in it,
you can escape them by using two double quotes instead of one:
msiexec /i myInstaller.msi PROPERTY1="Game title: ""Starcraft""."

You can clear a property by setting its value to an empty string, such as:
msiexec /i myInstaller.msi PROPERTY1=""

Properties declared on the command line override those set in your WiX markup.
So, you could declare a WiX Property element in your XML to give it a default
value, and then override that value from the command line.

Referencing properties

One of the common uses of properties is to reference them in another WiX element.
There is a limited list of elements that can reference a property, including the following:
•

Control: This references a Text attribute

•

ListItem: This references a Text attribute

•

Dialog: This references a Title attribute

•

Shortcut: This references Target, Arguments, and Description attributes

•

Condition: This references Message attribute

•

RegistryValue: This references Name and Value attributes

Generally, any attribute on an element that becomes something the end user will see
in the UI (text on dialogs, labels on buttons, items in lists, and so on) or the names
of shortcuts and registry keys will have the ability to interpret it. In the element's
attribute, add the Id attribute of the property with square brackets around it. For
example, to refer to a property called USERNAME, you'd use [USERNAME]. You'll run
across more elements like this throughout the rest of the book.
In the next example, we'll create a property called myProperty that has a value of
0. A Condition element that follows checks the value to see if it's equal to 1. Notice
that I'm using the square bracket notation in the Message attribute to reference
myProperty:





The Message attribute is used to show a modal window to the user. In this case,
they'll see Value of myProperty is 0. Should be 1.
Conversely, when you use a property in the inner text of an element, you don't
need the square brackets. Conditional statements, such as those found inside the
Condition element, are a good example. Look back at the previous example to see
that myProperty is referenced in the inner text of the Condition element without
using square brackets.


The Installed keyword is a built-in property set by WiX that
signifies that the product is already installed. By checking it, we
ensure that the second half of our condition will only be evaluated if
the product is not currently installed.

Declaring properties in your main .wxs file is fine if you only have a few. Once
you've got a good number it's easier to move them into their own source file and
nest them inside a Fragment element. To access these in your main .wxs file, add a
PropertyRef element with the Id attribute of one of the properties. A PropertyRef
element brings that property, and all others defined in the fragment, into the scope of
your project.

...






Property visibility and scope

Two things to consider when working with properties are visibility and scope.
With regards to visibility, consider that when you install an MSI package it's simple
to get a log of the process. You can see this log by installing from the command line
with logging turned on.
[ 80 ]

www.it-ebooks.info

Chapter 3

You can also turn on logging by changing keys in the registry or
through Group Policy. Refer to the following web page for more
information: http://support.microsoft.com/kb/223300.

The following command installs a package called myInstaller.msi and writes a
verbose log using the /l*v flag:
msiexec /i myInstaller.msi /l*v log.log

When you submit this command, it will log every event that happens during the
install to a text file called log.log. At the end of the log, all properties with their
values will be listed in plain text. This isn't a good thing if one of your properties
contains a password or other sensitive data. To prevent a specific property from
showing in the install log, mark it as Hidden:

Navigation menu