Using WiX to fix up XML files when deploying to different environments
I met Rob Mensching out at PDC and he pointed out a new feature in WiX that can be used to solve the problem of deploying XML configuration files into many different environments. It's called <XmlFile> and allows you to poke values into an XML file while deploying them. This is the same problem I try to solve with the XmlPreprocessor tool.
I was curious how it worked, so I wrote a sample to illustrate.
Let's start out with a configuration file that has a value in it that needs to change depending on the environment into which we are deploying. In this case we want to replace "localhost" with a different value for Dev, Test, and Production.
--sample.config--
<configuration>
<appSettings>
<add key="ServiceLocation" value="localhost"/>
</appSettings>
</configuration>
Here is the WiX script that creates an MSI that uses XmlFile. The value for [SERVICELOCATION] can be passed into the installer on the command line or collected in a UI.
--wixsetup.wxs--
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<Product Id="88DC12AD-74D8-415a-AFE7-83C1BE05A3EB" Name="XmlFile Sample" Language="1033" Version="1.0.0" Manufacturer="XmlFile">
<Package Id="????????-????-????-????-????????????" Description="Sample showing XmlFile used in a WiX setup." Comments="Sample showing XmlFile used in a WiX setup." InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="Product.cab" EmbedCab="yes" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="WiXSampl" LongName="XmlFile WiX Sample">
<Component Id="ProgramComponent" Guid="3D62CA0A-DE38-4687-95BE-1B200670E35A">
<File Id="_F86C7B1F61C44480BEFA68A2D045D7BB" Name="SAMPLE.CON" LongName="sample.config" src="sample.config" Vital="yes" DiskId="1"/>
<XmlFile Id="ModifyServiceLocation" Action="setValue" ElementPath="/configuration/appSettings/add[@key='ServiceLocation']/@value" File="[INSTALLLOCATION]\sample.config" Value="[SERVICELOCATION]"/>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="Complete" Title="XmlFile Sample" Level="1">
<ComponentRef Id="ProgramComponent" />
</Feature>
</Product>
</Wix>
If you want to try this yourself it only takes a couple minutes, get a hold of the latest WiX binaries from SourceForge, Then run the following batch file to compile the MSI (fix up wix_home to where you unzipped WiX).
--CreateSetup.bat--
set wix_home=C:\Tools\WiX
"%wix_home%\candle.exe" wixsetup.wxs
"%wix_home%\light.exe" -out wixsetup.msi wixsetup.wixobj "%wix_home%\ca\wixca.wixlib"
Deploy the MSI, passing in the parameters like this:
wixsetup.msi SERVICELOCATION=ABCDEFG
After deployment the configuration file will look like this:
--sample.config--
<configuration>
<appSettings>
<add key="ServiceLocation" value="ABCDEFG"/>
</appSettings>
</configuration>
That's good stuff.