Beruflich Dokumente
Kultur Dokumente
Overview
Windows
Installer
XML
(WiX,
pronounced
wicks)
is
a
free
software
toolset
that
builds
Windows
Installer
(MSI)
packages
from
an
XML
document.
It
supports
a
command-line
environment
and
later
gained
support
as
an
add-in
to
Visual
Studio
2008
and
2010.
Starting
with
Visual
Studio
2012,
it
came
bundled
as
the
only
Microsoft
blessed
installer
technology.
While
Microsoft
has
given
WiX
its
blessing
in
name,
it
has
done
little
to
support
it.
WiX
has
been
Microsofts
in-house
installer
technology
since
1999,
and
has
taken
incremental
steps
in
releasing
it
publicly.
Its
creator,
Rob
Mensching,
has
official
duties
at
Microsoft
and
supports
development
of
WiX
in
his
spare
time.
An
official
tutorial
has
long
served
WiX
developers
at
http://wix.tramontana.co.hu/tutorial.
It
was
created
in
2009
when
WiX
was
at
version
3.0.
This
walkthrough
is
based
on
that
tutorial,
but
updated
for
WiX
version
3.7
and
considerably
pared
down.
This
walkthrough
follows
the
source
code
available
for
download
from
my
website
at
http://www.schiffhauer.com/downloads/WiX-Solution.zip.
The
solution
contains
a
Sources
folder,
which
contains
four
files:
FoobarAppl10.exe
our
main
executable
Helper.dll
a
required
DLL
file
Manual.pdf
an
optional
instruction
manual
the
user
may
install
Exclam.ico
an
icon
we
will
use
to
signal
an
alert
to
the
user
during
installation
It
also
contains
four
small
WiX
Setup
Projects
and
a
Custom
Action
Project.
If
you
havent
before,
please
also
install
the
WiX
Toolset
v3.7
from
http://wixtoolset.org/.
The
WiX
source
is
also
good
to
have
on
hand.
The
WiX
Starter
project
is
an
example
of
a
new
project
as
Visual
Studio
creates
it.
It
consists
simply
of
a
Product.wxs
template
file.
In
the
WiX.01
project,
we
will
write
the
markup
necessary
to
build
an
installer
that
installs
the
main
executable,
the
required
DLL,
and
the
instruction
manual.
The
installer
will
not
yet
have
a
user
interface,
but
will
simply
perform
the
installation
when
launched.
<Product
Id="*"
Name="Foobar"
Language="1033"
Version="1.0.0.0"
Manufacturer="Chris's
Manufacturing
Conglomerate"
UpgradeCode="1af8578c-7b9c-4f09-ade0-011a92803559">
WiX
compiles
the
Product
Id
from
an
asterisk
into
a
Guid,
which
handles
upgrade
logic.
You
can
also
insert
your
own
Guid
value.
Weve
also
changed
the
name
and
added
a
Manufacturer,
which
is
a
required
field.
Since
the
optional
Keywords,
Description,
Comments,
and
Manufacturer
values
are
shown
in
the
MSI
package
properties
in
Windows,
Ive
included
them
in
my
markup.
InstallScope=perMachine
installs
the
package
for
all
users.
User
installation
can
be
customized
using
InstallScope=perUser.
InstallerVersion=200
indicates
that
the
minimum
version
of
WindowsInstaller
to
be
used
is
v2.0.
Compressed=yes
indicates
to
use
compressed
(.cab)
installer
files.
<Feature
Id="Complete"
Title="Foobar"
Level="1">
<!--
ComponentGroupRef:
Each
ComponentGroup
below
must
have
a
reference
-->
<ComponentGroupRef
Id="ProductComponents"
/>
<ComponentGroupRef
Id="Shortcuts"/>
</Feature>
Weve
named
our
single
feature
Foobar,
and
added
a
reference
to
a
Shortcuts
component
group
that
well
create
further
below.
<Fragment>
Our
first
fragment
lays
out
the
directory
structure
we
want
to
install.
It
makes
use
of
predefined
folder
IDs
as
well
as
folders
that
we
define.
<Directory
Id="TARGETDIR"
Name="SourceDir">
TARGETDIR
is
a
predefined
value
that
is
the
root
directory
of
WiX
Setup
Projects.
Every
directory
we
create
is
a
subelement
of
this
directory
Id.
(Be
aware
that
directories
that
are
defined
but
never
have
any
components
assigned
will
not
be
created
at
all.
This
befuddles
many
developers
attempting
to
create
empty
directories
with
the
installation
and
is
a
good
candidate
for
the
custom
actions
well
look
at
later.)
<Directory
Id="ProgramFilesFolder">
ProgramFilesFolder
usually
resolves
to
C:\Program
Files
(x86)\,
but
can
also
resolve
to
C:\Program
Files\
if
the
system
is
32-bit
or
youre
installing
a
64-bit
application.
ProgramMenuFolder
is
a
predefined
folder
for
start
menu
shortcuts,
and
DesktopFolder
is
a
predefined
folder
for
desktop
shortcuts.
Our
second
fragment
describes
our
software
components.
It
contains
the
two
component
groups
referenced
above.
The
ProductComponents
group
is
assigned
to
the
INSTALLFOLDER
directory,
which
weve
defined
as
C:\Program
Files
(x86)\WixTutorial.
Our
main
executable,
helper
DLL,
and
instruction
manual
will
be
installed
there.
Shortcuts
to
the
main
executable
will
be
created
in
the
ProgramMenuDir
and
DesktopFolder
directories.
The
shortcuts
Advertise=yes
tells
the
installer
to
disable
users
ability
to
edit
the
shortcut.
Also,
if
the
shortcuts
destination
no
longer
exists,
the
installation
is
considered
broken
and
the
installer
will
launch
to
try
to
repair
itself.
<ComponentGroup
Id="Shortcuts"
Directory="ProgramMenuDir">
<Component
Id="ProgramMenuShortcut">
<RemoveFolder
Id="ProgramMenuDir"
On="uninstall"
/>
<RegistryValue
Root="HKCU"
Key="Software\[Manufacturer]\[ProductName]"
Type="string"
Value=""
KeyPath="yes"
/>
</Component>
</ComponentGroup>
The
Shortcuts
group
contains
logic
to
remove
the
start
menu
item
when
the
application
is
uninstalled,
and
creates
a
registry
entry
as
the
KeyPath
to
detect
the
components
install
status.
So
if
the
installer
sees
that
this
registry
value
exists,
it
expects
the
entire
feature
to
be
installed.
The
only
time
a
component
does
not
require
a
KeyPath
is
if
it
has
a
single
File
element,
which
then
defaults
as
the
KeyPath.
<Fragment>
<Icon
Id="FoobarIcon.exe"
SourceFile="../Sources/FoobarAppl10.exe"
/>
</Fragment>
Our
final
fragment
sets
the
icon,
whose
Ids
extension
is
required
by
WiX
to
match
the
source
files
extension.
At
this
point,
the
application
can
be
built.
A
WiX.01.msi
installer
will
be
outputted
to
\Introduction
to
WiX\WiX.01
-
Completed\bin\Debug.
If
this
is
launched,
the
user
will
see
the
installers
progress
but
will
be
unable
to
stop
or
interact
with
it.
Now
well
close
the
WiX.01
project
files
and
look
at
the
WiX.02
project.
In
this
project,
well
add
the
markup
necessary
for
a
user
interface,
and
create
a
feature
tree
so
the
usual
can
select
the
features
to
install.
To
start,
Ive
added
a
reference
to
the
WixUIExtension
library.
We
will
find
this
library,
among
others,
in
the
WiX
Toolset
we
installed
earlier.
The
path
is
generally
C:\Program
Files
(x86)\WiX
Toolset
v3.7\bin.
In
the
Product.wxs
Feature
elements,
were
adding
Title
and
Description
attributes
to
each
Feature
element.
We
also
broke
the
manual
into
its
own
component
group
called
DocumentationComponents,
so
that
it
can
be
optionally
included
or
excluded
by
the
user.
We
wont
be
using
WiXs
Mondo
UI,
which
provides
Typical,
Custom,
and
Complete
options,
but
lets
take
a
quick
look
at
the
Feature
elements
Level
property.
Weve
set
the
ProductComponent
and
Shortcuts
groups
to
Level=1,
and
the
DocumentationComponents
group
to
Level=1000.
Any
Level
of
1-3
will
default
to
a
Typical
installation,
while
anything
higher
is
omitted
from
a
Typical
installation
but
is
available
in
Custom
or
Complete
options.
Our
feature
tree
will
reveal
both
features
but
default
the
Level
1000
group
to
be
excluded.
<UIRef
Id="MyWixUI_FeatureTree"
/>
The
UIRef
tag
within
the
Product
element
references
a
new
fragment
at
the
bottom
of
the
file,
which
links
to
a
new
Installer
file
well
create
shortly.
Lets
first
look
at
the
new
fragment:
<Fragment>
<UI
Id="MyWixUI_FeatureTree">
<UIRef
Id="WixUI_FeatureTree"
/>
<UIRef
Id="WixUI_ErrorProgressText"
/>
<DialogRef
Id="UserRegistrationDlg"
/>
<Publish
Dialog="LicenseAgreementDlg"
Control="Next"
Event="NewDialog"
Value="UserRegistrationDlg"
Order="3">LicenseAccepted
=
"1"</Publish>
<Publish
Dialog="CustomizeDlg"
Control="Back"
Event="NewDialog"
Value="UserRegistrationDlg"
Order="2">1</Publish>
</UI>
<Property
Id="PIDTemplate"><![CDATA[12345<###
###>@@@@@]]></Property>
<Property
Id="PIDKEY"
Hidden="yes"
/>
</Fragment>
The
two
UIRef
elements
refer
to
predefined
UI
elements.
The
DialogRef
Id
is
a
reference
to
the
UserRegistrationDlg
dialog
we
will
create.
What
follows
are
two
Publish
elements,
which
publish
events
when
we
click
on
controls
like
Next
or
Back
buttons.
We
will
use
them
to
insert
our
UserRegistrationDlg
between
the
predefined
LicenseAgreementDlg
and
CustomizeDlg
dialogs.
The
first
event
overrides
LicenseAgreementDlgs
Next
button
to
point
to
our
UserRegistrationDlg
instead
of
the
default
CustomizeDlg.
It
also
prevents
the
user
from
continuing
unless
the
License
Agreement
is
accepted.
The
second
Publish
element
links
the
subsequent
CustomizeDlgs
Back
button
back
to
our
UserRegistrationDlg
dialog.
Finally,
we
define
two
properties.
The
first
defines
a
format
that
WiX
will
use
to
create
two
text
boxes
of
three
characters
each,
which
only
accept
numbers.
Well
use
the
second
property
to
validate
the
users
product
key.
Creating UserRegistrationDlg.wxs
Add
an
Installer
File
called
UserRegistration.wxs.
The
initial
template
looks
like
this:
To
the
Fragment
element
I
have
added
a
UI
element
with
a
child
Dialog
element,
which
in
turn
has
many
Control
element
children.
Take
a
look
at
UserRegistration.wxs
in
the
WiX.02
project.
The
markup
is
mostly
self-explanatory.
<Dialog
Id="UserRegistrationDlg"
Width="370"
Height="270"
Title="[ProductName]
Setup"
NoMinimize="yes">
The
Dialog
elements
Title
contains
[ProductName],
which
simply
refers
back
to
the
Product
Name
in
Product.wxs.
As
in
Product.wxs,
here
we
define
the
events
to
publish
on
Back,
Next,
and
Cancel
buttons.
The
Back
button
returns
to
the
predefined
LicenseAgreementDlg.
The
Next
button
validates
the
product
key
(for
now
were
defaulting
this
to
1
or
true),
allows
Windows
to
verify
costing,
then
opens
the
predefined
CustomizeDlg.
The
ProductID
property
we
defined
in
Product.wxs
must
exist,
and
we
will
create
a
custom
action
below.
At
this
point,
you
can
compile
and
launch
the
application.
We
now
have
a
working
installer
with
a
user
interface
including
a
useful
feature
tree.
Lets
close
the
WiX.02
project
files
and
open
WiX.03.
In
this
project,
well
add
a
custom
action,
and
update
our
installer
to
implement
it.
Ive
also
created
a
CheckPID
Custom
Action
Project
in
C#.
You
can
also
create
custom
actions
in
VB
or
C++.
The
CustomAction.cs
in
my
provided
CheckPID
project
is
only
minimally
different
from
the
base
template.
After
naming
my
ActionResult
method
to
CheckPID,
Ive
added
two
lines
of
logic:
string
Pid
=
session["PIDKEY"];
session["PIDACCEPTED"]
=
Pid.StartsWith("1")
?
"1"
:
"0";
The
first
line
accepts
the
session
property
PIDKEY
that
we
defined
in
Product.wxs.
The
second
sets
a
new
PIDACCEPTED
property
to
true
if
the
key
starts
with
a
1,
or
false
if
otherwise.
Remember
to
add
your
new
Custom
Action
Project
as
a
project
reference
to
your
Setup
project.
Now,
returning
to
Product.wxs,
well
add
a
new
fragment
to
link
it
to
the
custom
action.
<Fragment>
<Binary
Id="CheckPID.CA"
SourceFile="..\CheckPID\bin\Debug\CheckPID.CA.dll"
/>
<CustomAction
Id="CheckingPID"
BinaryKey="CheckPID.CA"
DllEntry="CheckPID"
/>
</Fragment>
When
WiX
compiles
a
custom
action,
it
automatically
inserts
.CA
prior
to
the
DLL
extension
(and
provides
poor
debugging
if
we
get
this
wrong).
We
link
our
Binary
element
to
the
DLL
source
file,
and
attach
CustomActions
CheckPID
method
to
it.
We
also
need
to
update
our
existing
UserRegistrationDlg.wxs
file
<Control
Id="Next"
Type="PushButton"
X="236"
Y="243"
Width="56"
Height="17"
Default="yes"
Text="Next">
<Publish
Event="DoAction"
Value="CheckingPID">1</Publish>
<Publish
Event="SpawnDialog"
Value="InvalidPidDlg">PIDACCEPTED
=
"0"</Publish>
<Publish
Event="NewDialog"
Value="CustomizeDlg">PIDACCEPTED
=
"1"</Publish>
</Control>
The
first
event
references
the
CheckingPID
CustomAction
we
defined
alongside
the
Binary
in
Product.wxs,
which
itself
invokes
our
CheckPID
method.
The
value
of
1
tells
WiX
to
always
publish
this
event.
The
second
event
spawns
a
new
dialog,
which
well
create
shortly,
if
our
PIDACCEPTED
property
is
set
to
false.
The
third
event
simply
links
to
the
predefined
CustomizeDlg
dialog
if
the
PIDACCEPTED
property
is
set
to
true.
All
that
is
left
is
to
create
a
simple
InvalidPidDlg.wxs
dialog
with
a
UI
and
optional
Binary
tag:
<UI>
<Dialog
Id="InvalidPidDlg"
Width="260"
Height="85"
Title="[ProductName]
Setup"
NoMinimize="yes">
<Control
Id="Icon"
Type="Icon"
X="15"
Y="15"
Width="24"
Height="24"
ToolTip="Information
icon"
FixedSize="yes"
IconSize="32"
Text="Exclam.ico"
/>
<Control
Id="Return"
Type="PushButton"
X="100"
Y="62"
Width="56"
Height="17"
Default="yes"
Cancel="yes"
Text="Return">
<Publish
Event="EndDialog"
Value="Return">1</Publish>
</Control>
<Control
Id="Text"
Type="Text"
X="48"
Y="10"
Width="194"
Height="45"
TabSkip="no">
<Text>The
user
key
you
entered
is
invalid.
Please,
enter
the
key
printed
on
the
label
of
the
jewel
case
of
the
installation
CD.</Text>
</Control>
</Dialog>
</UI>
<Binary
Id="Exclam.ico"
SourceFile="../Sources/Exclam.ico"
/>
In
case
youve
never
entered
an
incorrect
product
key
before,
this
dialog
tells
the
user
that
their
key
is
invalid,
and
presents
them
with
a
single
button
that
closes
the
dialog
and
returns
to
the
registration
dialog.
We
also
finally
put
our
Exclam.ico
file
to
use.
In Conclusion
WiX
is
a
powerful
installer
technology
that
is
made
attractive
by
its
XML
markup
and
integrated
Visual
Studio
support.
However
its
lack
of
full
support
at
Microsoft,
and
especially
its
lack
of
support
resources,
makes
it
a
challenge
to
get
up
and
running
quickly.
The
next
step
is
to
visit
http://wixtoolset.org/
and
read
through
the
documentation.
It
would
also
be
worthwhile
to
go
through
the
full
tutorial
at
http://wix.tramontana.co.hu/tutorial.
While
it
is
a
few
years
old
it
covers
the
technical
nuts
and
bolts
to
the
extent
youll
need
to
progress
in
your
fluency
in
WiX
and
Windows
installer
in
general.
Bon
courage
!