Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / installer

A quick introduction: Create an MSI installer with WiX

4.58/5 (30 votes)
8 Dec 2010CPOL6 min read 364.6K  
This is a quick introduction for developers who want to create a simple MSI installer using the free WiX toolset v3.0.

Getting started


Here is what you need first:


1) On Windows XP you might need to download and install the Microsoft .NET Framework if you have none installed on your PC. The WiX toolset requires the .NET Framework, currently this is version 3.5 SP1. The installation takes some time, time to get a coffee.

2) Download and install the following file: WiX Toolset v3.0. WiX is a collection of free tools that builds software installers from XML documents.


You can build an installer from command line, but also use an IDE such as Visual Studio or Eclipse. Let's have a look at the tools and create an MSI file from command line.

Create your first WiX file


Create an XML file example.wxs as below:

XML
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
</Wix>


That's the absolutely minimum, let's add a little bit more:

XML
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111" 
            Name="Example Product Name" Version="0.0.1" Manufacturer="Example Company Name" Language="1033">
      <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
      <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>

      <Directory Id="TARGETDIR" Name="SourceDir">
         <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222"/>
      </Directory>

      <Feature Id="DefaultFeature" Level="1">
         <ComponentRef Id="ApplicationFiles"/>
      </Feature>
   </Product>
</Wix>


Create your first MSI installer


Create a batch file make_installer.bat as below:

BAT
candle example.wxs
light example.wixobj
@pause


Run it to build the package, ignore any warnings. In case you are curious: candle is the WiX compiler (generates an object file), light is the WiX Linker (generates the final installer).

There will be an example.msi in your folder now, congratulations! Double click it to install it, then go to Add/Remove Programs in the Control Panel where you can find an "Example Product Name". Don't forget to uninstall it, so you can later build and install a new MSI file.

Create a simple application installer


Copy an application into the same directory as your example.wxs, any standalone executable will do (for example C:\WINDOWS\system32\notepad.exe if you have nothing else available). Rename the application to example.exe. Change the following lines in your XML file example.wxs:

XML
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111" 
            Name="Example Product Name" Version="0.0.1" Manufacturer="Example Company Name" Language="1033">
      <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
      <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>

      <Directory Id="TARGETDIR" Name="SourceDir">
         <Directory Id="ProgramFilesFolder">
            <Directory Id="INSTALLDIR" Name="Example">
               <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
                  <File Id="ApplicationFile1" Source="example.exe"/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <Feature Id="DefaultFeature" Level="1">
         <ComponentRef Id="ApplicationFiles"/>
      </Feature>
   </Product>
</Wix>


Run make_installer.bat again to build the package and double click example.msi to install it. This time there will be a directory called Example in your Program Files folder and the example.exe will be installed there. You can uninstall your application via Add/Remove Programs in the Control Panel or right click on MSI file and choose Uninstall.

Create a start menu entry



This adds your example application to the start menu. Since a start menu entry is a shortcut and not a real file, a registry entry is needed. Change the following lines in your XML file example.wxs:

XML
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111" 
            Name="Example Product Name" Version="0.0.1" Manufacturer="Example Company Name" Language="1033">
      <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
      <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>

      <Directory Id="TARGETDIR" Name="SourceDir">
         <Directory Id="ProgramFilesFolder">
            <Directory Id="INSTALLDIR" Name="Example">
               <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
                  <File Id="ApplicationFile1" Source="example.exe"/>
               </Component>
            </Directory>
         </Directory>

         <Directory Id="ProgramMenuFolder">
            <Directory Id="ProgramMenuSubfolder" Name="Example">
               <Component Id="ApplicationShortcuts" Guid="12345678-1234-1234-1234-333333333333">
                  <Shortcut Id="ApplicationShortcut1" Name="Example Shortcut Name" Description="Example Product Name" 
                            Target="[INSTALLDIR]example.exe" WorkingDirectory="INSTALLDIR"/>
                  <RegistryValue Root="HKCU" Key="Software\Example Company Name\Example Product Name" 
                            Name="installed" Type="integer" Value="1" KeyPath="yes"/>
                  <RemoveFolder Id="ProgramMenuSubfolder" On="uninstall"/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <Feature Id="DefaultFeature" Level="1">
         <ComponentRef Id="ApplicationFiles"/>
         <ComponentRef Id="ApplicationShortcuts"/>
      </Feature>
   </Product>
</Wix>


Run make_installer.bat again, test and uninstall your example.msi.

How to do software upgrades



A little bit of configuration is needed for software upgrades, because some values are used repeatedly we define them as variables. Change the following lines in your XML file example.wxs:

XML
<?xml version="1.0"?>
<?define ProductVersion = "0.0.1"?>
<?define ProductUpgradeCode = "12345678-1234-1234-1234-111111111111"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Product Id="*" UpgradeCode="$(var.ProductUpgradeCode)" 
            Name="Example Product Name" Version="$(var.ProductVersion)" Manufacturer="Example Company Name" Language="1033">
      <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
      <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
      <Upgrade Id="$(var.ProductUpgradeCode)">
         <UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
         <UpgradeVersion Minimum="0.0.0" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="no" 
                         Property="OLDERVERSIONBEINGUPGRADED"/>	  
      </Upgrade>
      <Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>

      <Directory Id="TARGETDIR" Name="SourceDir">
         <Directory Id="ProgramFilesFolder">
            <Directory Id="INSTALLDIR" Name="Example">
               <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
                  <File Id="ApplicationFile1" Source="example.exe"/>
               </Component>
            </Directory>
         </Directory>

         <Directory Id="ProgramMenuFolder">
            <Directory Id="ProgramMenuSubfolder" Name="Example">
               <Component Id="ApplicationShortcuts" Guid="12345678-1234-1234-1234-333333333333">
                  <Shortcut Id="ApplicationShortcut1" Name="Example Shortcut Name" Description="Example Product Name" 
                            Target="[INSTALLDIR]example.exe" WorkingDirectory="INSTALLDIR"/>
                  <RegistryValue Root="HKCU" Key="Software\Example Company Name\Example Product Name" 
                            Name="installed" Type="integer" Value="1" KeyPath="yes"/>
                  <RemoveFolder Id="ProgramMenuSubfolder" On="uninstall"/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <InstallExecuteSequence>
         <RemoveExistingProducts After="InstallValidate"/>
      </InstallExecuteSequence>

      <Feature Id="DefaultFeature" Level="1">
         <ComponentRef Id="ApplicationFiles"/>
         <ComponentRef Id="ApplicationShortcuts"/>		 
      </Feature>
   </Product>
</Wix>


Two things are important for software upgrades: increase the ProductVersion in every new release, the UpgradeCode has to stay the same for all releases! Run make_installer.bat again, build two packages with different ProductVersion numbers and name them example_001.msi and example_002.msi. The installer will check if an old version is installed and replaces it, in case a newer version is already installed it will abort with an error message.

Final touches



Let's add icon and links for support information, they are are shown via Add/Remove Programs in the Control Panel. Copy an icon into the same directory as your example.wxs, any graphics file with ending ico will do (for example http://www.codeproject.com/favicon.ico if you have nothing else available). Rename the file to example.ico. Change the following lines in your XML file example.wxs:

XML
<?xml version="1.0"?>
<?define ProductVersion = "0.0.1"?>
<?define ProductUpgradeCode = "12345678-1234-1234-1234-111111111111"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Product Id="*" UpgradeCode="$(var.ProductUpgradeCode)" 
            Name="Example Product Name" Version="$(var.ProductVersion)" Manufacturer="Example Company Name" Language="1033">
      <Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
      <Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
      <Icon Id="ProductIcon" SourceFile="example.ico"/>
      <Property Id="ARPPRODUCTICON" Value="ProductIcon"/>
      <Property Id="ARPHELPLINK" Value="http://www.exampleproduct.com"/>
      <Property Id="ARPURLINFOABOUT" Value="http://www.examplecompany.com"/>
      <Property Id="ARPNOREPAIR" Value="1"/>
      <Property Id="ARPNOMODIFY" Value="1"/>
      <Upgrade Id="$(var.ProductUpgradeCode)">
         <UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
         <UpgradeVersion Minimum="0.0.0" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="no" 
                         Property="OLDERVERSIONBEINGUPGRADED"/>	  
      </Upgrade>
      <Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>

      <Directory Id="TARGETDIR" Name="SourceDir">
         <Directory Id="ProgramFilesFolder">
            <Directory Id="INSTALLDIR" Name="Example">
               <Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
                  <File Id="ApplicationFile1" Source="example.exe"/>
               </Component>
            </Directory>
         </Directory>

         <Directory Id="ProgramMenuFolder">
            <Directory Id="ProgramMenuSubfolder" Name="Example">
               <Component Id="ApplicationShortcuts" Guid="12345678-1234-1234-1234-333333333333">
                  <Shortcut Id="ApplicationShortcut1" Name="Example Shortcut Name" Description="Example Product Name" 
                            Target="[INSTALLDIR]example.exe" WorkingDirectory="INSTALLDIR"/>
                  <RegistryValue Root="HKCU" Key="Software\Example Company Name\Example Product Name" 
                            Name="installed" Type="integer" Value="1" KeyPath="yes"/>
                  <RemoveFolder Id="ProgramMenuSubfolder" On="uninstall"/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <InstallExecuteSequence>
         <RemoveExistingProducts After="InstallValidate"/>
      </InstallExecuteSequence>

      <Feature Id="DefaultFeature" Level="1">
         <ComponentRef Id="ApplicationFiles"/>
         <ComponentRef Id="ApplicationShortcuts"/>		 
      </Feature>
   </Product>
</Wix>


Download the final WiX installer example. Don't forget to replace text starting with "12345678-1234-1234-1234" with unique GUIDs in your final installer. Also check every place with text "example" and replace it with your product/company name.


Okay, that's it. You now know the basics and are ready to make your own MSI installer! :)

Find more information


Once you are familiar with a simple MSI installer, you probably want to add more files and a GUI. Here's where to find further information:

Most features can be added by adding more information to the XML file and changing the make file arguments.

Trouble shooting



  • A WiX command line tool crashes with the following error: The application failed to initialize properly (0xc0000135)?

    This is a known problem on Windows XP, you need to install the Microsoft .NET Framework, see above in the 'getting started' section.

  • A WiX command line tool gives the following error: program is not recognized as an internal or external command?

    You need to update the path and manually add the WiX binaries path, see how to set the path in Windows 2000/Windows XP. The default path for an English Windows XP is C:\Program Files\Windows Installer XML v3\bin ...you can find the correct path for your PC in the Windows Explorer, search for the file candle.exe (the name of the WiX compiler).

  • A WiX command line tool gives a CNDL0104 error: Not a valid source file?

    Make sure your XML file is valid. Use an XML editor or for a quick check open the file in Firefox, it will show XML parsing errors in red.

  • Installing or updating .NET Framework takes forever?

    Yes, better get another coffee. There will also be one or more reboots, you will have lots of waiting time.

  • The .NET Framework installed a Firefox add-on without asking for permission, how do I get rid of it?

    The easiest way is to open the Firefox menu Tools -> Add-ons -> Microsoft .NET Framework Assistant and click on 'Disable'. This won't uninstall it, for further information on how to completely remove it see KB963707.

  • My example MSI file won't install and nothing happens, what can I do?

    MSI files require administrative privileges, make sure you are installing the MSI examples as administrator.

  • Some of the WiX tutorial from the internet don't work, why is that?

    There are different versions of WiX, the current version is WiX v3.0 (at time of writing). If tutorials and blogs give contradicting information, it's because they haven't labelled which version of WiX they used. For example v2.0 is obsolete and v3.5 is planned with new features you can't use yet.

  • How do I generate GUIDs for my installer?

    There are command line tools available or create GUIDs online. You will need at least one for the UpgradeCode and one for each component in the XML file.


Conclusion


Advantages:

  • Write a Windows installer with free tools (WiX is open source)
  • WiX configuration can be done in any XML or text editor
  • Easy integration into automated build scripts
  • Multi language install packages are possible (via undocumented MSI hack)
  • Active mailing list for support


Disadvantages:

  • GUI customisation is difficult, the default templates are usually not sufficient
  • Localisation is incomplete in WiX v3.0, e.g. no Swedish, Danish, Norwegian, Finnish (according to WiX Localization Project)
  • Documentation is old and incomplete, you have to search trough various blogs
  • Underlying MSI installer concept is complex and time consuming to learn, MSI is not a simple package manager
  • File system and registry cleanup is not made particular easy, you often have to write custom actions for uninstall/upgrade
  • Software versions are limited to 3 parts of the version (major.minor.build) or software upgrades won't work


External links


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)