Spinner Software Home About
KB Contact

Creating MSI setup files using XML source code and the WiX open source project

Published: 2004 - Last update: 2004 (c) Nicolai Kjaer / Spinner Software B.V.

1.0 Installing

Note: You must have Microsoft .NET framework installed before you can use WiX.

Download the binaries for Windows from http://sourceforge.net/projects/wix, then extract the zipfile to the location you want to have WiX installed.

Once installed, add the location of candle.exe to your PATH environment variable.

Please note that there is a bug in the current WiX release, so your Regional Settings MUST BE EXACTLY AS FOLLOWS to prevent the date/time error with light.exe:

Date = "MM/dd/yyyy"
Time = "HH:mm:ss"

Tip: You might want to create a shortcut to the doc\wix.chm file. This help file also contains the full schema reference for the WiX XML.

Please take extreme care with your XML - it IS CASE-SENSITIVE.

2.0 Your first MSI

First, we will create the smallest possible MSI. This MSI has 1 feature with 1 component, and you should be able to install and remove it as any other MSIs.

Note: In these examples, WiX is installed in D:\Data\WiX\, and under there is a subdirectory named Projects\Test. The Test project files are kept here. Remember to change the paths to point to the proper location on your system.

Create a textfile called Test.wxs:

<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
	<Product Id='12345678-1234-1234-1234-123456789012' Title='My MSI' 
		Name='Test Package' 
		Language='1033' 
		UpgradeCode='12345678-1234-1234-1234-123456789001' 
		Version='1.0.0.0' 
		Manufacturer='Spinner Software'>

		<Package Id='12345678-1234-1234-1234-123456789012' 
		Description='My first Windows Installer package' 
		Comments='This is my first attempt at creating a Windows Installer database' 
		Manufacturer='www.spinner.nl' 
		InstallerVersion='200' 
		Keywords='MSI,Example' 
		Compressed='yes'/>

		<Directory Id='TARGETDIR' Name='SourceDir'>
			<Component Id='MyComponent' 
			Guid='12345678-1234-1234-1234-123456789012' />
		</Directory>

		<Feature Id='MyFeature' Title='My 1st Feature' Level='1'>
			<ComponentRef Id='MyComponent' />
		</Feature>
	</Product>
</Wix>

Compiling: Candle and Light

Create a command file that will compile the Test project:

@ECHO OFF
@ECHO.
@ECHO Compiling %1
@ECHO.
IF "%1"=="" GOTO ERR
SET SRCDIR=D:\Data\WiX\Projects\Test

@ECHO Removing old files
DEL /Q %1.wixobj
DEL /Q %1.msi

REM Pass the sourcefile to Candle.exe
@ECHO Precompiling ..
Candle %1.wxs
IF NOT EXIST %1.wixobj GOTO CompileError

@ECHO Compiling ..
Light %1.wixobj -b %SRCDIR%\ -v0 -notidy
IF NOT EXIST %1.msi GOTO CompileError

@ECHO.
@ECHO Project %1 compiled succesfully
@ECHO.
GOTO END

:CompileError
@ECHO.
@ECHO Unable to compile project %1
@ECHO.
GOTO END

:ERR
@ECHO.
@ECHO Syntax: Compile Projectname
@ECHO.

:END
PAUSE

Create a Test.cmd command file/script to compile your Test project:

Compile.cmd Test

Now, run test.cmd and make sure it can compile properly. Then test the MSI before you continue.

To simply the testing, you can create a small install.cmd textfile:

@ECHO OFF
@ECHO.
@ECHO Installing Test.msi
@ECHO.
SET SRCDIR=D:\Data\WiX\Projects\Test
MsiExec /i "%SRCDIR%\test.msi" /l*v "%SRCDIR%\test_i.log" /Qb+
@ECHO.
@ECHO Done
@ECHO.
REM PAUSE

Check that the installation runs, and results in an entry under Add/Remove Programs.

To uninstall it again, create a small textfile named uninstall.cmd:

@ECHO OFF
@ECHO.
@ECHO Removing Test.msi
@ECHO.
SET SRCDIR=D:\Data\WiX\Projects\Test
MsiExec /x %SRCDIR%\test.msi /l*v %SRCDIR%\test_x.log /Qb+
@ECHO.
@ECHO Done
@ECHO.
REM PAUSE

2.1 Customizing the MSI

You will need to create and use real GUIDs. Use GUIDGEN (from MS Visual C++) with the Registry format to obtain GUIDs, and remember to UPPERCASE all letters.

If you open the MSi file with Orca, you can see that the Title in the Summary Stream is "Installation Database". You cannot change this from the XML source.

3.0 Adding registry keys

To install a registry key, add a Registry entry under your TARGETDIR directory entry:

<Component Id='COMP0001' Guid='12345678-1234-1234-1234-123456789012'>
	<Registry Root="HKLM" Key="SOFTWARE\Spinner Software\TestMSI" 
		Name="ProductName" 
		Value="[ProductName]" 
		KeyPath="yes" Id="REG00001" />
</Component>

4.0 Adding files

To install a file, add a Component with a File entry under your directory entry:

<Component Id="COMP0002" Guid="12345678-1234-1234-1234-123456789012">
	<File Id="FILE0003" Name="GPL.txt" LongName="GPL.txt" KeyPath="yes" DiskId="1" />
</Component>

You must also have a Media entry under your Product entry:

<Media Id="1" Cabinet="Files" CompressionLevel="high" EmbedCab="yes" LastSequence="1" />

5.0 Adding shortcuts

To add a shortcut, create a Shortcut entry under a component:

<Directory Id="ProgramMenuFolder" Name=".">
	<Directory Id="DIR00004" Name=".">
		<Directory Id="DIR00005" Name="Spinne~1" LongName="Spinner Software">
			<Directory Id="DIR00006" Name="TestMSI" LongName="TestMSI">
				<Component Id="COMP0003" Guid="12345678-1234-1234-1234-123456789012">
					<Shortcut Id="SCUT0001" Directory="DIR00006" Name="Spinner.nl" LongName="Spinner website" Target="[ARPHELPLINK]" Description="Our website" Icon="IEXPLORE.EXE" IconIndex="0" Show="normal" />
				</Component>
			</Directory>
		</Directory>
	</Directory>
</Directory>

The icon you use must also be added under the Product entry:

<Icon Id="IEXPLORE.EXE" src="Icons\IEXPLORE.EXE" />

6.0 Adding properties

You can add Property entries under the Product entry:

<Property Id="ALLUSERS">1</Property>
<Property Id="ARPHELPLINK">http://www.spinner.nl</Property>

Please enclose the ARPHELPLINK property in a CDATA section.

9.0 Using Dark

If you have already created your basic MSI from scratch, you can use Dark to decompile the MSI file into a WiX XML source file. This works on any valid MSI. The syntax is:

Dark InputMSI.msi OutputWXS.wxs

To export the binaries as well, specify the -x parameter and a path:

Dark InputMSI.msi OutputWXS.wxs -x D:\Data\WiX\Projects\Test\

10.0 Appendix - Sample WXS file

The following WiX example source file will, once compiled, result in an MSI that installs a HKEY_LOCAL_MACHINE registry key, a file, and a shortcut.

For this example to work, you must have the following files under the directory containing the wxs file:

Icons\IEXPLORE.Exe 
(copy from C:\Program Files\Internet Explorer\).
Program Files\Spinner Software\TestMSI\GPL.txt 
(copy from WiX installation directory).

Once you have created these subdirectories and copied the files, create the Test.wxs file:

<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
	<Product Id='BBA7AA3D-D0CD-430A-A544-B54D146ED921' Title='My MSI' 
		Name='Test Package' 
		Language='1033' 
		UpgradeCode='12345678-1234-1234-1234-123456789001' 
		Version='1.0.0.0' 
		Manufacturer='Spinner Software'>

		<Package Id='E23C2186-8CD1-48EE-89FD-80ED0ABA752B' 
		Description='My first Windows Installer package' 
		Comments='This is my first attempt at creating a Windows Installer database' 
		Manufacturer='www.spinner.nl' 
		InstallerVersion='200' 
		Keywords='MSI,Example' 
		Compressed='yes'/>

		<Directory Id='TARGETDIR' Name='SourceDir'>
			<Component Id='COMP0001' Guid='5B08A940-EB73-4843-A598-6B27B9476A43'>
				<Registry Root="HKLM" Key="SOFTWARE\Spinner Software\TestMSI" 
					Name="ProductName" 
					Value="[ProductName]" 
					KeyPath="yes" Id="REG00001" />
			</Component>

			<Directory Id="SystemFolder" Name="." />
			<Directory Id="PersonalFolder" Name="." />
			<Directory Id="DesktopFolder" Name="." />
			<Directory Id="StartMenuFolder" Name="." />

			<Directory Id="ProgramFilesFolder" Name=".">
				<Directory Id="DIR00001" Name="." SourceName="PROGRA~1" LongSource="Program Files">
					<Directory Id="DIR00002" Name="Spinne~1" LongName="Spinner Software">
						<Directory Id="DIR00003" Name="TestMSI" LongName="TestMSI">
							<Component Id="COMP0002" Guid="BFEE7267-86AB-4277-B3FF-761D01343365">
								<File Id="FILE0001" Name="CPL" LongName="CPL.txt" KeyPath="yes" DiskId="1" />
							</Component>
						</Directory>
					</Directory>
				</Directory>
			</Directory>

			<Directory Id="ProgramMenuFolder" Name=".">
				<Directory Id="DIR00004" Name=".">
					<Directory Id="DIR00005" Name="Spinne~1" LongName="Spinner Software">
						<Directory Id="DIR00006" Name="TestMSI" LongName="TestMSI">
							<Component Id="COMP0003" Guid="B1E7EAE9-C652-4DD1-AFFC-88E8D761B9D7">
								<Shortcut Id="SCUT0001" Directory="DIR00006" Name="Spinner.nl" LongName="Spinner website" Target="[ARPHELPLINK]" Description="Our website" Icon="IEXPLORE.EXE" IconIndex="0" Show="normal" />
							</Component>
						</Directory>
					</Directory>
				</Directory>
			</Directory>

		</Directory>

		<Icon Id="IEXPLORE.EXE" src="Icons\IEXPLORE.EXE" />

		<Media Id="1" Cabinet="Files" CompressionLevel="high" EmbedCab="yes" LastSequence="1" />

		<Property Id="ALLUSERS">1></Property>
		<Property Id="ARPHELPLINK">http://www.spinner.nl</Property>

		<Feature Id='Complete' Title='Complete installation' Level='1'>
			<ComponentRef Id="COMP0001" />
			<ComponentRef Id="COMP0002" />
			<ComponentRef Id="COMP0003" />
		</Feature>
	</Product>
</Wix>

Remember to enclose the ARPHELPLINK property in a CDATA section.

Tip: If you encounter a problem with files during compiling - for example Light will try to move an existing file into the same file - check that the Compressed="yes" attribute it set for the Package entry.

Tip: If the Windows Installer package is started but not installed, check the log file. If it looks like "nothing happens", validate the MSI. If that looks ok, check that the Windows Installer service is started, and that the SYSTEM account has read access rights to the MSI file and the directory containing it.

--------------------------------------------------------------------------------

(c) 2004 Nicolai Kjaer, Spinner Software B.V.

http://www.spinner.nl