Using Wix how can I deploy one of several web.config files while installing an ASP.net web application

StackOverflow https://stackoverflow.com/questions/8603462

Question

I'm using Wix 3.6 beta from the command line, not as VS projects. I have a web application that is harvested with heat as a directory. This works. I'm using web.config transforms to manage each of the target environment web.config files. These are output with msbuild, this works and keeps things visible in Visual Studio and source control.

I've hit a problem deploying one of the several web.config files which I am manually including in product.wxs as components with conditions. I was expecting to include all components as deployable features and let the conditions select just one as active. For example:

        <DirectoryRef Id="wwwroot">
        <Component Id="setup_a" Guid="some_guid" >
            <File Source="$(var.ConfigSourceDir)\setup_a\web.config"  />
            <Condition>ENVIRON = setup_a</Condition>
        </Component>

        <Component Id="setup_b" Guid="some_guid" >
            <File Source="$(var.ConfigSourceDir)\setup_b\web.config" />
            <Condition>ENVIRON = setup_b</Condition>
        </Component>

This didn't create any file renaming, moving or deleting issues, but has the very fundamental problem that multiple web.config files are mapped to the same destination and this gives me a light error of "Product.wxs(xxx) : error LGHT0091 : Duplicate symbol 'File:web.config' found. This typically means that an Id is duplicated. Check to make sure all your identifiers of a given type (File, Component, Feature) are unique."

An alternative approach was to use different named .config files and rename/move one to be the web.config, so something like:

        <DirectoryRef Id="wwwroot">
                <Component Id="setup_a" Guid="some_guid" >
                <File Id="setup_a.config" Source="$(var.ConfigSourceDir)\setup_a.config"  />
                <CopyFile Id="moveit" SourceDirectory="wwwroot" SourceName="setup_a.config" DestinationDirectory="wwwroot" DestinationName="web.config"  />
               </Component>

This doesn't throw an error, bot the CopyFile command does nothing at all. I just get setup_a.config in the wwwroot folder.

If I nest the CopyFile inside the File, the copy action then works:

        <DirectoryRef Id="wwwroot">
               <Component Id="setup_a" Guid="some_guid" >
               <File Id="setup_a.config" Source="$(var.ConfigSourceDir)\setup_a.config"  >
                    <CopyFile Id="moveit" DestinationName="web.config"/>
               </File>
               </Component>

...but nested CopyFile means I can't add (it's disallowed) the Delete="yes" attribute to create a 'move' action. Instead I'm left with both setup_a.config and web.config in the wwwroot folder. Alternatively, if I add a seperate removefile within the same component element it also does nothing:

<RemoveFile Id="removefile" On="install" Directory="wwwroot" Name="setup_a.config"/>
</Component>

So, I'm hoping for a working example of how handle multiple web.config files in a conditional deployment, that doesn't leave files behind. the destination filename of web.config is fixed by the framework and can't be changed. The different configs are also pre-generated outside of wix using config transforms, this also can't be changed but the generated filenames could be anything.

cheers!

Was it helpful?

Solution

You complicate it too much. This should work:

    <Component Id="setup_a" Guid="some_guid" >
        <File Name="web.config" Id="config_a" Source="$(var.ConfigSourceDir)\setup_a\web.config"  />
        <Condition>ENVIRON = setup_a</Condition>
    </Component>

    <Component Id="setup_b" Guid="some_guid" >
        <File Name="web.config" Id="config_b" Source="$(var.ConfigSourceDir)\setup_b\web.config" />
        <Condition>ENVIRON = setup_b</Condition>
    </Component>

Pay attention to a couple of things here:

  • the File/@Name is the same - that's the target file name you'd like to have (web.config)
  • the File/@Id is different for each File in order to avoid the light error you mentioned first
  • the File/@Source can be anything - it just describes what file to take as a source

In this sample light will still complain with warning LGHT1076, but that's just a warning - it pays your attention that conditions MUST be mutually exclusive to avoid problems.

OTHER TIPS

I usually take a different approach. Rather then placing multiple mutually exclusive files into an installer that are tightly coupled to specific instances I put a generic file in the installer and use XML changes to transform the XML with the variation point data such as connection string and what not.

This allows me to make installers that can be deployed anywhere silently just by passing a few properties and the command line.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top