[wix-users] CustomAction - both Read AND Write Properties

Walter Dexter wfdexter at gmail.com
Wed Oct 16 14:06:04 PDT 2019

@Rob - Thanks, I've seen that and read it repeatedly but it's not really
making a lot of sense to me. The last part of the page does and describes
how I got it to work to read the properties from the MSI in deferred mode.

@Edwin - Thanks, and your second paragraph actually solved it for me. I
spent a lot of time today running in circles because I screwed up the
"Session.Log()" calls in the DLL (session.log("blah {0}",blerp) does NOT
work) and now that I've circled back and fixed them and looked at what I
can get in session["property name"] I see that I can read them in immediate

The CA just needs to take three MSI properties, read a file, and set four
more MSI properties, and that works great in immediate mode, so yippee,
problem solved!

It sure would have been nice if the interface were the same in both
execution modes.

Both of your responses are much appreciated!.


On Wed, Oct 16, 2019 at 3:20 PM Edwin Castro <egcastr at gmail.com> wrote:

> You've kind of already figured all of this out.
> An immediate custom action can read and write properties and make other
> changes to the msi database. It runs in the client context and cannot make
> any changes to the system yet. An immediate custom action does not have
> custom action data.
> A deferred custom action runs in the server context and it can make
> changes to the system but it does not have access to most properties. The
> little bit of data it does have access to is read only. Most data available
> to a deferred custom action is provided via a special property called
> custom action data. An immediate custom action can set that special
> property by setting a property with the name of the custom action.
> The strategy you want to use is to write an immediate custom action that
> determine what needs to happen and a deferred custom action that does the
> actual work. These two custom actions communicate via the special custom
> action data property written by the immediate custom action and read by the
> deferred custom action as custom action data.
> In your case, I would probably write an immediate custom action that reads
> the data file and uses the various properties to select which bits of data
> are written to the INI file. Then that same custom action would write the
> data as a list of entries into an appropriate property that represents the
> custom action data for a second custom action. The second custom action is
> deferred and it reads the custom action data, parsing it if necessary and
> writes the data into the destination INI file. If the second custom action
> doesn't have to run all the time, then you might consider scheduling it
> from the immediate custom action only when you need it.
> --
> Edwin G. Castro
> On Wed, Oct 16, 2019 at 12:40 PM Walter Dexter via wix-users <
> wix-users at lists.wixtoolset.org> wrote:
>> Can someone confirm this is impossible so I can stop banging my head on
>> the
>> wall - or tell me how to do it?
>> I'm writing a CustomAction in C#. I wanted to pass in some of the MSI
>> properties, lookup some stuff in files on the file system and set some
>> more
>> of the MSI properties.
>>    - If I set the Execute attribute to "immediate" then CustomActionData
>>    (that I setup with a type 51 custom action) doesn't get passed in, but
>> I
>>    can update the MSI properties from the CA.
>>    - If I set the Execute attribute to "deferred" then CustomActionData
>>    does get passed in, but I can't update the MSI properties from the CA.
>>    - There don't appear to be any other Execute attribute values that make
>>    any sense to make it any better.
>> I'm pasting in the relevant chunk of my WXS file below.
>> What's going on here is the DLL CA looks in a strangely formatted text
>> file
>> ("DNS.TXT") to get the DNS servers from "nar.na.test" and "nar.na.corp"
>> records, then IN_STAGING property is used to decide which set to write to
>> the INI file.
>> IN_STAGING is set if a flag file (staging.flag) exists. I'm just working
>> off the requirements handed me, but I assume that file would be created on
>> our test systems but not in production locations.
>> If there's something else I've done that is stupid I'm glad to hear that
>> feedback as well. :)
>> I'm probably going to give up and just hard-code the three properties in
>> the CA DLL but I didn't really want to. I wanted the DLL to be as
>> non-specific as possible and all that sort of stuff passed in from the MSI
>> so when they decide that everything needs to be somewhere else I can just
>> tweak a property and move on.
>> Thanks for any help-
>> Walt
>> ----------------------------------------------------------------------------------------------------------------------------------------------------------
>> <!-- Where to find the DNS addresses -->
>> <Property Id="DNS_TXT_FILE"    Value="c:\pos_backup\network\dns.txt"
>> Secure="yes" />
>> <!-- staging and production domain names -->
>> <Property Id="STAGING_DOMAIN"  Value="nar.na.test" Secure="yes" />
>> <Property Id="PROD_DOMAIN"     Value="nar.na.corp" Secure="yes" />
>> <!-- config file to update -->
>> <Property Id="CONFIG_INI_PATH"
>> Value="c:\pos_backup\storage\xpestaging\tools\config.ini" Secure="yes" />
>> <!-- Package up the above properties for the custom action to use. -->
>> <CustomAction Id="CA_GetDNSDLL_Properties" Return="check"
>> Property="CA_GetDNSDLL"
>> />
>> <!-- Custom action puts DNS servers in these properties. -->
>> <Property Id="PRI_PROD" Secure="yes" />
>> <Property Id="SEC_PROD" Secure="yes" />
>> <Property Id="PRI_STAGING" Secure="yes" />
>> <Property Id="SEC_STAGING" Secure="yes" />
>> <!-- Determine if staging.flag file exists and therefore if system is in
>> staging. Otherwise production -->
>> <Property Id="IN_STAGING" Secure="yes" >
>>     <DirectorySearch Id="DS_IN_STAGING" Path="DIR_ISPCONFIG" >
>>         <FileSearch Id="FS_IN_STAGING" Name="staging.flag" />
>>     </DirectorySearch>
>> </Property>
>> <!-- Get the DNS addresses -->
>> <Binary Id="GetDNSDLL"
>> SourceFile="..\..\source\GetDNSCA\obj\x86\Release\GetDNS.CA.dll" />
>> <CustomAction Id="CA_GetDNSDLL" BinaryKey="GetDNSDLL" DllEntry="GetDNS"
>> Execute="immediate" Return="check" />
>> <!-- Update the config.ini file - production values. -->
>> <Feature Id="W10_CONFIGINI_DNS" Title="Set CONFIG.INI DNS for Windows 10
>> project" Level="1" >
>>     <!-- Not in staging = production. -->
>>     <Component Id="CMP_PROD_DNS" Directory="DIR_STAGING"
>> Guid="{869128EF-0FCA-4B44-B935-CA22079134FE}" Transitive="yes" >
>> Source="files/config.proddns.dll" KeyPath="yes" />
>>         <IniFile Id="IF_PROD_DNS_PRI" Name="config.ini" Action="addLine"
>> Directory="DIR_STAGING" Section="Network" Key="DNS_PRIMARY"
>> Value="[PRI_PROD]" />
>>         <IniFile Id="IF_PROD_DNS_SEC" Name="config.ini" Action="addLine"
>> Directory="DIR_STAGING" Section="Network" Key="DNS_SECONDARY"
>> Value="[SEC_PROD]" />
>>         <Condition><![CDATA[NOT IN_STAGING]]></Condition>
>>     </Component>
>>     <!-- In staging = staging. -->
>>     <Component Id="CMP_STAGING_DNS" Directory="DIR_STAGING"
>>  Guid="{1F10F5D4-BDD7-4718-8BD2-3F5CFAA391EB}" Transitive="yes" >
>> Source="files/config.stagdns.dll" KeyPath="yes" />
>>         <IniFile Id="IF_STAGING_DNS_PRI" Name="config.ini"
>> Action="addLine"
>> Directory="DIR_STAGING" Section="Network" Key="DNS_PRIMARY"
>> Value="[PRI_STAGING]" />
>>         <IniFile Id="IF_STAGING_DNS_SEC" Name="config.ini"
>> Action="addLine"
>> Directory="DIR_STAGING" Section="Network" Key="DNS_SECONDARY"
>> Value="[SEC_STAGING]" />
>>         <Condition><![CDATA[IN_STAGING]]></Condition>
>>     </Component>
>> </Feature>
>> <InstallExecuteSequence>
>>     <RemoveExistingProducts After="InstallInitialize" />
>>     <!-- These three also for Windows 10 Config.ini change -->
>>     <!-- Suppress the INI value remove because the uninstall will also be
>> deleting the whole file. -->
>>     <!-- CA_GetDNSDLL pulls the DNS addresses out of the DNS.TXT file. -->
>>     <Custom Action="CA_GetDNSDLL_Properties" Before="CA_GetDNSDLL" />
>>     <!-- <Custom Action="CA_GetDNSDLL" Before="CostFinalize" /> was this
>> before I changed the CA above to deferred from immediate.-->
>>     <Custom Action="CA_GetDNSDLL" Before="WriteIniValues" />
>> </InstallExecuteSequence>
>> ____________________________________________________________________
>> WiX Toolset Users Mailing List provided by FireGiant
>> http://www.firegiant.com/

More information about the wix-users mailing list