Background
Our development team has
been working on projects with basically a .Net flavored stack. We are creating
WPF clients for services using WCF with SQL 2008 on the backend. Instead of
Team Foundation Server there was an organizational decision to use the Atlassian
suite of project management tools: Jira with Greenhopper, Bamboo, and Fisheye.
Currently we are still using Subversion but there is some movement towards
using Atlassian's Stash with Git.
We were primarily using
Visual Studio Installer Setup Projects to create our installers. It was
relatively simple when be started, but became more involved as we created
custom actions and extended the installers. With Microsoft dropping support of
the Setup projects (http://blogs.msdn.com/b/buckh/archive/2011/03/17/visual-studio-setup-projects-vdproj-will-not-ship-with-future-versions-of-vs.aspx)
and a rather abrupt shift to using Visual Studio 2012 we needed to implement a
Wix solution for our installers in rapid order.
The Wix tutorial (http://wix.tramontana.co.hu/tutorial)
is fantastic and really quite thorough, but it only deals with building from an
IDE like VisualStudio in general terms. So, I thought I'd compile what I did
for walking through the tutorial using Wix 3.7 and Visual Studio 2012.
Getting Started
I'll assume you have Visual
Studio 2012 and the Wix toolset (http://wixtoolset.org/ v3.7: http://wix.codeplex.com/releases/view/99514).
Also you should review the tutorial. My walk-through is in no way meant to be
as comprehensive as that tutorial, but rather to get one started using Wix with
Visual Studio 2012. The tutorial also does a good job explaining 'candle' and
'light' and the other associated tools in the Wix toolkit. Finally, at least
initially I will use the sample files from the tutorial: a simple executable,
dll library, and user manual (http://wix.tramontana.co.hu/system/files/samples/SampleFirst.zip).
- The Software Package
I start by selecting File > New > Project in VS. If you have the Wix toolset installed you should see a Wix Setup Project template under Templates > Visual C# > Windows Installer XML.
I start by selecting File > New > Project in VS. If you have the Wix toolset installed you should see a Wix Setup Project template under Templates > Visual C# > Windows Installer XML.
I created my project with the name “WixTutorial”.
Wix has now created a Setup Project and an initial Product.wxs
file.
The Product element has a wildcard “*” in the Id field. The
wildcard will be turned into a random GUID at compile time. This isn’t
necessarily a big deal since the recommended approach is to always to a major
upgrade as opposed to minor upgrades or patches, but until I understand the
upgrade process a bit better I’m replacing the wildcard with a generated GUID.
By default the Id field in other elements that haveuse GUIDs as ID are
defaulted to the wildcard. From what I’ve seen so far this is actually
preferred even for components providing you are using the single file per
component approach (http://stackoverflow.com/questions/1602831/wix-one-file-per-component-or-several-files-per-component/1604348#1604348).
While Wix adds the Language attribute to the Product
(defaulted to ‘1033’ - English) it does not add the Codepage attribute, which
is the character set used. I don’t know if this is simply defaulted to ‘1252’
now or is based on the Language attribute. As multi-language support is beyond
the scope of this now, I’m just leaving it.
To the Package element I also add the Keywords, Description,
Comments, and Manufacturer attributes as these are shown in the properties of
the MSI package in Windows. The InstallerVersion is the minimum version of
WindowsInstaller to be used. Wix has set this to 200 (WindowsInstaller v2.0)
and I will leave this until it warrants some change. Compressed=”yes” indicates
to use compressed (.cab) installer files. The InstallScope attribute is new
since the tutorial. InstallScope=”perMachine” sets the installation scope for “All
Users”. This can also be set to “perUser”. The “perMachine” installation will
require elevated permissions to install the software.
The MajorUpgrade element tells MSI how to handle product
upgrades. For now the default that Wix has in is sufficient. I’ve added the EmbedCab=”yes” attribute to
the empty MediaTemplate element that Wix created. This way my .cab files will
be packaged in the .msi file. I’m not using the separate Media elements as the
tutorial describes as I don’t plan to put the installer on separate media. The tutorial
explains how to use this, however.
Finally Wix has added a feature element with a child
ComponentGroupRef element. This differs from the tutorial, which has us create
the entire directory hierarchy with the components within it. Instead Wix has
created the directory structure and components within separate fragments. The
tutorial explains this approach in Upgrades and Modularization > Fragments (http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization/fragments),
and I think it is a cleaner approach and easier to refactor common elements later.
I changed the default Id and Title to fall in line with the tutorial. The Level
is used to determine if the feature should be installed in a “Typical”, “Custom”
or “Complete” installation. For our main feature it should be left at 1.
I also added a second ComponentGroupRef element that will
refer to my shortcut files as those get installed to a different directory than
our main install directory.
<Product Id="E240A99B-A6A2-41A6-A8F9-DF388EBAD98B" Name="Fubar 1.0" Language="1033"
Version="1.0.0.0" Manufacturer="Dominion Voting
Systems" UpgradeCode="585749c0-d21d-453f-bcbf-a565bbf0431d">
<Package Keywords="Installer" Description="FUBAR Test Wix Installer"
Comments="This is a test
installer package." Manufacturer="Dominion Voting Systems" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="Complete" Title="Fubar 1.0 Complete" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="Shortcuts" />
</Feature>
</Product>
The Files Inside
As described in the tutorial we lay out a hierarchical directory
structure that Windows Installer will recreate upon installation. It then installs
the components into the directories to which they are assigned. The top level
directory has a predefined name “TARGETDIR”. The next level also uses a
predefined name “ProgramFilesFolder” to indicate to MSI to install to the Windows
Program Files directory. (A complete list of predefined names is here: http://kb.flexerasoftware.com/selfservice/viewContent.do?externalID=Q105880)
. Finally we have an “INSTALLFOLDER” directory. This is not a predefined
directory. INSTALLFOLDER is the ID that we will use to refer to the directory
when assigning components. The Name attribute of the Directory is the name the
directory will have in Windows.
We are also going to reference two more directories that use
the Installer’s predefined names in order to place our shortcuts: the
ProgramMenuFolder and the DesktopFolder, which reference the start menu
Programs menu and the Desktop respectively. Within the ProgramMenuFolder we
create our own directory for our application called “Fubar 1.0”.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WixTutorial" />
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="Fubar 1.0" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
</Fragment>
The nesting indicates our hierarchy. This fragment tells the
installer to create one directory named “WixTutorial” inside of our Program
Files directory. This is usually C:\Program Files (x86). Note that Wix will not
create directories with no components. However, the tutorial explains using the
CreateFolder element in a component to create an empty directory (http://wix.tramontana.co.hu/tutorial/com-expression-syntax-miscellanea/creating-directories).
The second fragment that Wix provided describes our software
components. The tutorial describes the component as the “atomic level” of thing
to be installed. I think it’s probably more correct to think of it as the “molecular
level” as a component can be composed of several VERY STRONGLY RELATED things,
those things being files, registry keys, and shortcuts. However, as I mentioned
before, it’s probably best to only have a single file in any given component.
Only one file can be assigned the “KeyPath” attribute, the path that MSI will
look at to determine if the entire component is installed. If the user accidentally
deletes an installed file that is not the KeyPath file while leaving the
component’s KeyPath file intact, that related file will not be restored by a “Repair”
or even minor update.
The components are contained in a ComponentGroup element.
This is a better way to put related files together without sticking them in the
same component. Here we associated the ComponentGroup feature with the
INSTALLFOLDER directory above meaning the components of the group will be
installed to the “WixTutorial” directory. As directed, we’ll delete the
comments that Wix put in and add our three file components to this group.
The first component is our main executable, FoobarAppl10.exe
(I copied this along with the other components from the sample file download to
my VS solution’s directory.) along with a Program Files shortcut and desktop
shortcut. You’ll notice that I did not give the Component a GUID Id. As long as
there is only a single file in the Component that GUID will be generated by the
compiler. Each Component should have a unique string Id, however. I did not add
a KeyPath=”yes” attribute to the file element either. The KeyPath will default
to the single file within the component. Finally, I don’t have the the DiskId attribute that the tutorial
includes as that relates to the Media element that I chose to ignore for now.
For each File element there is a Name attribute. This is the
name that the file will have when installed. The Source of the File, meaning
the path to file to be packaged in the installer package, will default to this
Name attribute. Since all three components are in the same directory as the Wix
package I can just leave off the Source attribute.
The FoobarEXE file has two shortcuts as children. These
shortcuts will be installed to the Program File directory and Desktop directory
that we referenced when we set up the directory structure. Since they are
children of the executable file, that file is automatically their target. The
Icon attribute references the name of the Icon element to use as the shortcut.
This name must have the same extension as the file that the shortcut points to.
That Icon element (which I will add in a minute) can have the EXE as a source
and the EXE can have multiple ICO files embedded within it. So you can add an
IconIndex as the tutorial shows, but our executable has one generic icon and
the index defaults to 0 (I believe). Finally Shortcuts can be advertised or
normal Windows shortcuts. A normal windows shortcut just points to a file path
and command and those can be changed by the user. An advertised shortcut is
essentially more closely bound to the file. The link to it cannot be changed
and if the shortcut cannot find the file it targets the installer will try and repair
the installation and reinstall the targeted file.
We’ll add two more components the HelperLibrary and the
instruction manual. The Manual also has a shortcut. This one has no icon so
will just show up in our Program Files menu with a generic icon and the name “Fubar
Instructions”.
I’ve added another ComponentGroup that we referenced above,
the Shortcuts components. This component includes a RemoveFolder element and a
RegistryValue element. RemoveFolder is
an element that you want to include if your application creates any directories
that you want to clean up when a user uninstalls the application. Even though
the installer is creating our ProgramMenuDir directory to hold our Program
Files shortcuts, the compiler will fail unless we specifically tell it to clean
up this directory on uninstall. My assumption is that because shortcuts are
specific to the user profile that it needs to clean those up in a user-by-user
basis. Thus we add a registry key for the current user that will be used as the
keyPath to see if that program menu directory has been installed.
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="MainExecutable">
<File Id='FoobarEXE' Name='FoobarAppl10.exe'>
<Shortcut Id='startmenuFoobar10' Directory='ProgramMenuDir' Name='FUBAR Tutorial 1.0' WorkingDirectory='INSTALLDIR' Icon='FoobarIcon.exe' Advertise='yes' />
<Shortcut Id='desktopFoobar10' Directory='DesktopFolder' Name='FUBAR Tutorial 1.0' WorkingDirectory='INSTALLDIR' Icon='FoobarIcon.exe' Advertise='yes' />
</File>
</Component>
<Component Id='HelperLibrary'>
<File Id='HelperDLL' Name='Helper.dll' />
</Component>
<Component Id='Manual'>
<File Id='Manual' Name='Manual.pdf'>
<Shortcut Id='startmenuManual' Directory='ProgramMenuDir' Name='Fubar Instructions' Advertise='yes' />
</File>
</Component>
</ComponentGroup>
<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>
</Fragment>
The final fragment to our file defines our Icon source for
the executable. While the Id must have the same extension as the file that the
shortcuts target, it does not have to have the same name as the file itself.
<Fragment>
<Icon Id="FoobarIcon.exe" SourceFile="FoobarAppl10.exe" />
</Fragment>
Putting It To Use
At this point you can right-click on the project in Solution
Explorer and do Build. Wix will ‘candle’ (compile) and ‘light’ (link) the
appropriate files. If you go to the Project Folder and then bin > Debug you
should have a new msi file. If you install this you will see the Installer fire
up, show some progress and voila! Your application is installed.
If you go to your Program Files (x86) folder you should see the
WixTutorial directory (or whatever you named your INSTALLFOLDER) and under it
should be the three component files. In your start menu > All Programs you
should see the “Fubar 1.0” (or whatever you named ProgramMenuDir) and under
that the two shortcuts for the executable and instructions. Finally on your
desktop should be an Icon for the executable.
You can remove the application either through the Control Panel or
by right-clicking on the .msi and clicking uninstall. Uninstalling should remove
all the files, directories, and shortcuts.
To Be Continued
In near-future posts I plan on walking through the User Interface,
Events and Actions (which includes Custom Actions), and the SQL sections of the tutorial. I do want to learn
more about Upgrades and Localization and will post about that when those things
become pertinent to what we are doing. I also want to look at creating both Web
and Windows services and probably user creation in conjunction with that.
10 comments:
Nice little intro to using Wix. Thanks.
The only other thing that may have added some value was a quick mention of project references and variables:
http://wix.sourceforge.net/manual-wix3/votive_project_references.htm
Good point. Thanks for adding that reference.
Thanks for this, this was a great "cliff notes" version.
One question.... your InstallScope is per machine. Shouldn't this mean your registryvalue root refer to HKLM?
Nice tutorial, thanks for sharing.
Please help me about how to check product version and .NET framework and please describle about user32.dll in check version. Thank you so much.
Best Regards,
Thuan
thuanpq78@yahoo.com
Hi, nice description.Thanks for your help..
-Aparna
Theosoft
Great mister.
It would be interesting to be continued in near-future posts walking through the User Interface, Events and Actions (Custom Actions).
Maybe soon near-future posts?
Nice tutorial, Thanks. I've tried to create new installer and notice that Repair wont update my exe file. What i'm missing ? here is my wxs file https://drive.google.com/file/d/0B8nKPU4xJkD3UHNSQlhNUEZJUDQ/edit?usp=sharing
Very good getting started guide. Helped enormously
great guide - very well done - i will check out what else wix related you have
thank yu
Post a Comment