Search code examples
c#wixwindows-installercustom-action

Passing Dynamic Properties to Deferred Custom Actions WIX


I want to pass the install directory to my different custom actions. I have the property

<Property Id="CA1Action" Value="InstallDir=[INSTALLFOLDER]"/>

Then I defined a CA in Wix

<CustomAction Id="CA1Action"
          BinaryKey="InstallerActionsBinary"
          DllEntry="CA1"
          Execute="commit"
          Return="check" />

For completion, I call my CA as

<Custom Action="CA1Action" After="InstallFiles"></Custom>

Executing my installer with MSIEXEC, I get the following error message from my custom action which tries to open a file from the install:

Could not find file 'C:\Windows\Installer\MSICA8C.tmp-\C:\Program Files\MyProgram\web.config'.

Here is the way I am extracting information from the session:

public static ActionResult CA1(Session session_)
{
        //Collect parameters from Session
        CustomActionData data = session_.CustomActionData;
        string path = data["InstallDir"];
}

My first question is why is the cache of the installer added to my parameter? To further add to my confusion, when I added

path = path.Substring("C:\Windows\Installer\MSICA8C.tmp-\".Length);

to my CA to remove "C:\Windows\Installer\MSICA8C.tmp-\", I get an argument exception telling me that the start value of the substring is higher than the length of my string ..So I added logging to my CA, and am seeing that path is getting set to '[INSTALLFOLDER]', not the value of the property, but then how is it the value of the property when I use it in the path for my FileStream?

I was following the replies in this post: How to pass parameters to the custom action?


Solution

  • It's not clear why you are using a commit custom action and then sequencing it after InstallFiles. Commit Custom Actions run after InstallFinalize. Most likely you should just have a deferred custom action.

    The other issue is that defining a property called CA1Action with a value that includes [INSTALLFOLDER] isn't likely to work because [INSTALLFOLDER] isn't defined until after any UI or other custom actions that set its value. What you need is an explicit "set property" custom action that is sequenced just before your actual custom action call. The example you link to has one called SetDirProp.

    So you may be seeing the installer cache folder because the values aren't initialized properly, or because you are in the commit stage. You are likely to see unexpected locations anyway, because the binary will be streamed out to some location where it can be run from, so a tmp or installer cache location is possible, but either way it's an implementation detail related to wherever the framework decides to stream to.