Sunday, November 28, 2010

WiX: Set properties from managed Custom Action and change config/xml files

This time my area to learn was: Set installation properties from “ini” file for a specific environment and use that to change some values inside configuration files (in my case only xml-based).

I naively started with classic ini file just to find out after banding my head that windows installer would be looking for it in the “windows” folder. I just can imagine the look of our deployment admin when telling him he needs to copy some ini file to the windows folder before installation.

So I looked a bit into how to have some ini file location by convention. Lets see what is AppDomain.CurrentDomain.BaseDirectory: C:\WINDOWS\Installer\MSID38.tmp-. Hmmm, same as Environment.CurrentDirectory. When we look at Environment.CommandLine we can see  why:

rundll32.exe "C:\WINDOWS\Installer\MSIE46.tmp",zzzzInvokeManagedCustomActionOutOfProc SfxCA_148644750 8 Tools.Wix.Actions!Tools.Wix.Actions.CustomActions.CustomAction1


So my next best option was to pass the properties file path via msiexec command line argument:

msiexec /i C:\Install\Debug\Cz.Sts.SelfCare.Integration.Setup.msi /l*v c:\i.txt ENVIRONMENT=C:\Install\Debug\sampleenvironment.xml

I was afraid for a moment while reading on stackoverflow that it didn’t work to someone (and here), but luckily enough it worked for me with no issue (I’m on wix 3.5):

string environmentPath = session["ENVIRONMENT"];

In the wxs file I put my task to be executed before the CostFinalize (as I was setting installation directories as well):

    <InstallExecuteSequence>
      <Custom Action="Tools.Wix.Actions.SetProperties" Before="CostFinalize" />
    </InstallExecuteSequence>

And then the only step left was to use XmlFile from utils for changing configuration values. You can see example for the app.config here, and I’m providing a sample for Spring.NET objects file:

            <Component Id="comp_STSCZ_SELFCAREINTEGRATION_36" DiskId="1" KeyPath="yes" 
                       Guid="34BE0011-B20E-4F86-9D59-D58596330CDF">
              <File Id="file_STSCZ_SELFCAREINTEGRATION_36" 
                    Source="..\Cz.Sts.SelfCare.Integration.Router.Host\bin\Debug\
Config\Common\LoggingObjects.xml" /> <util:XmlFile Id="LoggingSetDirectory" Action="setValue" Permanent="yes"
File="[#file_STSCZ_SELFCAREINTEGRATION_36]" ElementPath="/objects/object[\[]@name='XmlLogger'[\]]/
constructor-arg[\[]@name='logRootLocation'[\]]"
Name="value" Value="[LogDirectory]" /> </Component>

You will find source code in the next entry. Happy coding to You!

No comments: