'Trying to read a file and then write a file during a WiX install in a CustomAction

I am having a tough time with this. There are a lot of SO articles about these settings but I'm still stuck.

My goal is to perform two steps:

  1. Read a file that will be physically shipped with the msi. In other words, there will be three files setup.exe, test.msi, specialFile.txt

  2. During the install, I want to create a new file in the install path. C:\Program Files\MyCompany\MyApplication\newFile.txt

The file in step 2 is created by reading something out of specialFile.txt from step 1.

My problem is navigating the murky combinations of WiX settings to enable me to read session variables and have high enough privs to write the file out. This has not been easy.

Here is what I've been doing:

<Binary Id="MyCustomAction.CA.dll" SourceFile="path\to\MyCustomAction.CA.dll" />
<CustomAction Id="MyActionsName"
    Return="check"
    Execute="deferred"
    BinaryKey="MyCustomAction.CA.dll"
    DllEntry="MyCustomAction"
    Impersonate="no"/>

    <CustomAction Id="CustomAction1"
        Property="LookupUnattendedXML"
        Value="INSTALLFOLDER=[I_Can_Get_This_From_The_Directory_Tags];SOURCEDIR=How_To_Get_This???"/>
    
<InstallExecuteSequence> 
    <Custom Action="CustomAction1" Before="MyActionsName" />
    <Custom Action="MyActionsName" Before="InstallFinalize">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>       
  • impersonate="no" in order to have enough privs to write the file
  • Execute is "deferred" in order to have enough privs to write the file (I don't understand how this works)
  • The Custom tag is set to Before="InstallFinalize". I tried other settings for this. Before="InstallFinalize" seems to fire after the files have been installed.

Then in the C# code, I appear to need to access session to get what I need. I ask for session["sourceDir"] to figure out where the .msi was launched from and then search for specialFile.txt This won't work with "deferred" turned on. I also access a Directory ID called INSTALLFOLDER which is supposed to refer to the path where the application is installed. It appears to do that. session["INSTALLFOLDER"]

The last wrinkle is that when I execute the .msi directly (no bootstrapper) and with deferred changed to immediate, I am able to read the session["sourceDir"] and it's really the location of the .msi as I wanted. When I use the setup.exe bootstrapper, this same variable points to an internal System directory where it appears that the MSI was copied to. I would like to let the user have both methods of execution (with and without the setup.exe bootstrapper) and somehow be able to access these paths.

UPDATE:

This article and this article about custom properties in deferred actions have enabled me to read the install folder in the custom action (now I know where to write the file to). A remaining challenge is figuring out the location of the MSI so I can read the file without using session["SourceDir"] because the Custom Action is deferred.



Solution 1:[1]

This would have solved the issue:

<Binary Id="MyCustomAction.CA.dll" SourceFile="path\to\MyCustomAction.CA.dll" />
<CustomAction Id="MyActionsName"
    Return="check"
    Execute="deferred"
    BinaryKey="MyCustomAction.CA.dll"
    DllEntry="MyCustomAction"
    Impersonate="no"/>

    <CustomAction Id="MyActionsName.CustomActionData"
        Property="MyActionsName" <!-- this is important -->
        Value="INSTALLFOLDER=[I_Can_Get_This_From_The_Directory_Tags];SOURCEDIR=[SOURCEDIR];ORIGINALDATABASE=[OriginalDatabase]"/>
    
<InstallExecuteSequence> 
    <Custom Action="MyActionsName.CustomActionData" Before="MyActionsName" />
    <Custom Action="MyActionsName" Before="InstallFinalize">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>   

In the custom action you can access the data set in MyActionsName.CustomActionData via session.CustomActionData["propertyname"]

In general you have to pass each variable/property you want to use of the 'normal' installation explicitly to the deferred custom action to show up in CustomActionData.

I've just seen that I'm very late. But maybe someone else will find this helpful.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1