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.

11 Comments

  • 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=&quot;/configuration/appSettings/add[@key='dbconnection']/@value&quot;



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



    I'm running WiX v2.0.3309

  • 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.

  • 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,






  • 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"

  • 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

  • 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,...

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

    can any one help me.

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

    Thaks!

    Alejandra

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

  • 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.

  • Great Stuff, very useful. Thanks a lot!

Comments have been disabled for this content.