Alex Shevchuk

Always listen to experts. They’ll tell you what can’t be done, and why. Then do it. - Lazarus Long

Property does not exist or empty when accessed from deferred custom action

Property does not exist or empty when accessed from deferred custom action

  • Comments 5
  • Likes

Problem

Property is created, but when deferred custom action tries to get its value - property either does not exist or its value is empty.

Sample

Let's test it with immediate custom action first to make sure that property has a value:

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

<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">

 

  <Product Id="{94A35E02-D48F-48F1-AC1A-23F62489BBF4}"

           Name="Minimal Windows Installer Sample"

           Language="1033"

           Codepage="1252"

           Version="1.0.0"

           Manufacturer="Acme Corporation"

           UpgradeCode="{74069BA4-1D1C-4252-A074-B2EC0C746403}">

 

    <Package Id="{4C159FD5-135E-42DE-B36E-22DDDCBA3DCF}"

             Description="Minimal Windows Installer Sample"

             Comments="This installer database contains the logic and data required to install [ProductName]."

             InstallerVersion="200"

             Languages="1033"

             SummaryCodepage="1252"

             Platforms="Intel"

             ReadOnly="no"

             Compressed="yes"

             AdminImage="no"

             Keywords="Installer"

             ShortNames ="no"

             Manufacturer="Acme Corporation" />

 

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

 

    <Directory Id="TARGETDIR" Name="SourceDir">

      <Directory Id="ProgramFilesFolder">

        <Directory Id="INSTALLDIR" Name="Minimal" LongName="MinimalInstallation">

 

          <Component Id="Component1"

                     Guid="{A77C5B06-132D-4884-8E17-EA10A83C812D}">

            <File Id="ReadMe" DiskId="1" Name="Readme.txt" Source="Readme.txt" Vital="yes" KeyPath="yes" />

          </Component>

 

        </Directory>

      </Directory>

    </Directory>

 

    <Property Id="TESTPROPERTY" Value="Hello" />

 

    <CustomAction Id="ShowProperty" Script="vbscript" Execute="deferred">

      <![CDATA[

      MsgBox Session.Property("TESTPROPERTY")

      ]]>

    </CustomAction>

 

    <InstallExecuteSequence>

      <Custom Action="ShowProperty" Before="InstallFinalize">Not Installed</Custom>

    </InstallExecuteSequence>

 

    <Feature Id="Feature1"

             Title="Feature1 title"

             Description="Feature1 description"

             Level="1"

             ConfigurableDirectory="INSTALLDIR" >

      <ComponentRef Id="Component1" />

    </Feature>

 

  </Product>

</Wix>

As you can see I explicitly set the value of the TESTPROPERTY property.  Custom Action Type 38 shows the message box with the value of this property.  Build MSI and test it.

Now, let's make our custom action ShowProperty deferred:

    <CustomAction Id="ShowProperty" Script="vbscript"

                  Execute="deferred">

      <![CDATA[

      MsgBox Session.Property("TESTPROPERTY")

      ]]>

    </CustomAction>

Let's test it again.  As you can see, the message box is empty.

Why?

As you can see in this article on MSDN, deferred custom action can access only three property:

Also, this article is saying that we need to add custom action to set the property with the same name as deferred custom action to the value of property we want to use in the deferred custom action.  Defereed custom action must access CustomActionData property.  Here is updated version:

    <Property Id="TESTPROPERTY" Value="Hello" />

 

    <CustomAction Id="ShowProperty" Script="vbscript" Execute="deferred">

      <![CDATA[

      MsgBox Session.Property("CustomActionData")

      ]]>

    </CustomAction>

 

    <CustomAction Id="SetPropertyForShowProperty"

                  Property="ShowProperty" Value="[TESTPROPERTY]" />

 

    <InstallExecuteSequence>

      <Custom Action="SetPropertyForShowProperty" Before="InstallInitialize">Not Installed</Custom>

      <Custom Action="ShowProperty" Before="InstallFinalize">Not Installed</Custom>

    </InstallExecuteSequence>

I've added new immediate Custom Action Type 51 to set the property with the name ShowProperty (same name as deferred custom action) and scheduled it in the InstallExecuteSequence table just before InstallInitialize standard action.  Custom Action ShowProperty is using CustomActionData property now.

Build the MSI and make sure that it is working now.

What if I need more than one property?

If we need to access more than one property, we must pack them into CustomActionData.  For example, if we know for sure that our properties will not have semi-colon in their value, we can concatenate property values and separate values using semi-colon.  Here is an example:

    <Property Id="TESTPROPERTY" Value="Hello" />

    <Property Id="TESTPROPERTY2" Value="World" />

 

    <CustomAction Id="ShowProperty" Script="vbscript" Execute="deferred">

      <![CDATA[

      Dim properties

      properties = Split(Session.Property("CustomActionData"), ";", -1, 1)

      MsgBox properties(0) & ", " & properties(1) & "!"

      ]]>

    </CustomAction>

 

    <CustomAction Id="SetPropertyForShowProperty"

                  Property="ShowProperty"

                  Value="[TESTPROPERTY];[TESTPROPERTY2]" />

 

    <InstallExecuteSequence>

      <Custom Action="SetPropertyForShowProperty" Before="InstallInitialize">Not Installed</Custom>

      <Custom Action="ShowProperty" Before="InstallFinalize">Not Installed</Custom>

    </InstallExecuteSequence>

 

Comments
  • Thanks a lot for this article. You are great.

    Regards

    Rakib Hasan

  • while installation of msi i was watching at process explorer ..i see multiple msiexec.exe are runing when i see properties i see like this

    C:\WINDOWS\system32\MsiExec.exe -Embedding 59465E02FC8CDF15571B52DDDD811C42

    i come to know this is for deffered custom action and i got the template like this..

    msiexec.exe -Embedding <GUID> - this is the custom action server (indicated by the -Embedding switch)

    here i have doubt what is <GUID> weatehr it stand for component ,Product or what its is...??

  • I don't know what this GUID is. It might be something which is meaningful to this particular run of the installer and during next run this GUID for the same custom action could be completely different.

  • What if I want to set a property value from a deferred custom action

  • Hi nice article, how to change value of property using custom action data ?

    Please reply to swapprakash@yahoo.co.in if you have solution for this.

    Thanks in advance.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment