Preserving properties used during install


Русская версия здесь.


 


One of the most common questions is how to preserve the value of property used during install (either passed through command line or properties like INSTALLLOCATION which can be changed in the UI) so that it can be used during maintenance or uninstall.


For example, here is one of the possible situations.  Consider this very simple example.  The idea here is that user passes the value to be written in the xml file through command line parameter.  We need to make sure that during repair that value will be preserved in the xml file.  Here is the source WiX file:


<?xml version=1.0 encoding=UTF-8?>


<Wix xmlns=http://schemas.microsoft.com/wix/2006/wi


     xmlns:util=http://schemas.microsoft.com/wix/UtilExtension>


 


  <?define UpgradeCode=”{D1C829D8-5A5B-412C-90ED-7F92750F8152}”?>


  <?define CurrentVersion=”1.0.0.0″?>


 


  <Product Id=*


           Name=PreserveProperty


           Language=1033


           Version=$(var.CurrentVersion)


           Manufacturer=PreserveProperty


           UpgradeCode=$(var.UpgradeCode)>


    <Package InstallerVersion=200


             Compressed=yes


             InstallScope=perMachine


             Languages=1033 />


 


    <Media Id=1 Cabinet=media1.cab EmbedCab=yes />


 


    <!– Make sure properties are passed in the command line –>


    <Condition Message=MYPROPERTY variable must be set in the command line>


      Installed OR MYPROPERTY


    </Condition>


   


    <!– Installation –>


    <Directory Id=TARGETDIR Name=SourceDir>


      <Directory Id=ProgramFilesFolder>


        <Directory Id=INSTALLLOCATION Name=PreserveProperty>


          <Component Id=ProductComponent


                     Guid=cf13f922-e33c-4b78-a849-46e32c000e09>


 


            <File Id=XmlFile


                  Name=test.xml


                  Source=test.xml


                  KeyPath=yes />


            <util:XmlFile Id=SetMYPROPERTY


                          Action=setValue


                          ElementPath=//config/parameter[\[]@name=’MyProperty'[\]]/@value


                          Value=[MYPROPERTY]


                          File=[#XmlFile] />


           


          </Component>


        </Directory>


      </Directory>


    </Directory>


 


    <Feature Id=ProductFeature Title=PreserveProperty Level=1>


      <ComponentRef Id=ProductComponent />


    </Feature>


  </Product>


</Wix>


To make sure MYPROPERTY is in the command line we will be using Custom Action Type 19 (<Condition> element).


Installer will install test.xml file and update value of the attribute to value of MYPROPERTY property.  Here is the content of test.xml:


<config>


 <parameter name=MyProperty value= />


</config>


If you will compile this sample and install it, you’ll see that test.xml is created and its value is set to provided value in the command line.  Try it with the following command line:


msiexec /i PreserveProperty.msi MYPROPERTY=”123″


You can also try to install it without providing MYPROPERTY.  Installation should fail with error message from <Condition> element.


Now, after installation is done, try to repair the installation.  After repair is completed, open test.xml.  You will see that the value of attribute is empty.  The problem is that during repair MYPROPRTY=”123″ is not passed to msiexec.exe.  It is our responsibility to preserve the value of property passed to msiexec.exe during initial install.


Let’s modify our WiX file to:



  1. Save the value of property in registry during initial installation

  2. Recover saved value from registry during AppSearch

  3. Set the value of MYPROPRTY to value recovered from registry provided that this is NOT initial install

First item is straightforward:


<RegistryKey Id=PreservePropertyInRegistry


             Root=HKLM


             Key=SOFTWARE\ACME Corp Action=createAndRemoveOnUninstall>


  <RegistryValue Id=SavedProperty


                 Action=write


                 Type=string


                 Name=SavedProperty


                 Value=[MYPROPERTY] />


</RegistryKey>


Second item is just plain vanilla RegistrySearch: 


<Property Id=SAVEDMYPROPERTY Secure=yes>


  <RegistrySearch Id=FindSavedMYPROPERTY


                  Root=HKLM


                  Key=SOFTWARE\ACME Corp


                  Name=SavedProperty


                  Type=raw


                  Win64=no />


</Property>


Third item is simple <SetProperty> (or Custom Action Type 51, if you still use V2), but conditioned to be executed during all types of install other than fresh install:


<SetProperty Id=MYPROPERTY After=AppSearch Value=[SAVEDMYPROPERTY]>


  Installed


</SetProperty>


Source code for this sample is in attachment. 


 

PreserveProperty.zip

Comments (2)

  1. Ran Davidovitz says:

    Although registry is a good approach, would it be possible to use data driven approach and persist this into a new table?

  2. Alex Shevchuk says:

    Hi Ran. No, persisting to table would not work because all these changes will be temporary. Changes will be saved in in-memory copy of original MSI.  See http://blogs.technet.com/alexshev/archive/2008/02/21/how-windows-installer-engine-installs-the-installation-package.aspx for more information.