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

Edwin Castro egcastr at gmail.com
Wed Oct 16 13:20:13 PDT 2019

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