Loren Halvorson's Blog

If your only tool is a hammer...

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.

Comments

Otto said:

Thanks for the tip. I've run into a problem though. I have multiple appSettings (keys) but when I try to edit them it's only the value of the first key that gets changed, no matter what ElementPath I specify. For instance:
ElementPath="/configuration/appSettings/add[@key='dbconnection']/@value"

Would not change the dbconnection key but defaultPageTitle which is first in my web.config.

I'm running WiX v2.0.3309
# October 26, 2005 11:19 AM

Tom said:

I have a scenario requiring a complex node to be added.

Is there an easier way of doing this than one attribute/element value pair at a time?  

Further, I can't see a reliable way of navigating back to a newly created element when it is one of many.  

My situation requires that I *not* have a value for the element that I am trying to relocate after the initial XmlFile call.  

Without the abililty to add a complex node, I'm considering using last() (or [1], whichever is appropriate) to navigate back to my node, but I'm fairly sure this is bad practice.

# November 2, 2006 7:50 PM

Raj said:

To Otto,

Hi all,

I am facing a problem with xpath... i wat to update my web.config file with two values. But i am able to update the first key element , its not updating the second element... can any body help me to resolve this one.

Here wat i am doing,

<XmlFile Id="ModifyDBServernameLocation" Action="setValue" ElementPath="/configuration/appSettings/add[@key='SERVICELOCATION']/@value" File="[TARGETDIR]\sample.config" Value="[SERVICELOCATION]"/>

<XmlFile Id="ModifyReportServerLocation" Action="setValue" ElementPath="/configuration/appSettings/add[@key='SERVICELOCATION']/@value" File="[TARGETDIR]\sample.config" Value="[SERVICELOCATION]"/>

# May 29, 2007 8:39 AM

Mike said:

to Raj,

the post here has some problems in the Path attribute:

1. you need to use "//" instead of "/" at the very beginning of the path

2. you need to enclose any [ or ] with [\]

so

your correct path would be:

ElementPath="//configuration/appSettings/add[\[]@key='SERVICELOCATION'[\]]/@value"

# August 16, 2007 8:48 AM

jayakumari said:

Hi,

 I am a new wix user. i need to create wix installer for my project. i found need to creat a wxs files. Is that any dynamic though which i can tell my dlls and Exes path.

And, i could not understand the value for id paramter.

how do we get 32 digit value for those id files. and how do i will integrate with my project/solution to the wix installer... if you can get me some info about creation of wxs file would be greate.. Many thanks in advance...

Cheers,

Jaya

# September 13, 2007 6:05 AM

joao said:

anyone know if i can put o xml config a value of an Edit

i create on wix a Dialog with one Edit,

in installation user put a text,

and on XML put that text,...

# November 13, 2007 1:57 PM

chandrashekar said:

Hi,

i want read value from one xm l and set that value in other xml file.

can any one help me.

# November 6, 2008 3:42 AM

SS said:

Do you have any tips if I want to add 20 files into 1 component. Should I use <File Id=.....> 20 times, I just need to copy the whole directory

# December 23, 2008 10:49 PM

Alejandra said:

Hello, how cann I configure, that the msi installer ask if I want to install the files?

Thaks!

Alejandra

# May 13, 2009 2:11 PM

Ram said:

Thanks for tips on WiX script. I have done changes in my WiX script file and tested the installer and it works fine.

# June 17, 2009 8:43 AM

The other mike said:

Mike, including a "//" at the beginning of the xpath tells it to search for that node. the "/" says to start at the root. His xpath is correct in that sense.

Properly escaping the brackets is important.

# July 29, 2009 4:04 PM

Chris Chambers said:

Great Stuff, very useful.  Thanks a lot!

# March 4, 2010 5:56 AM