Search code examples
c#wixcustom-actionwindows-installer

Writing MSI property to registry created through WiX custom action


I would like for the MSI installer I'm creating with WiX to run a Custom Action that creates and encrypts an installer property (a date) which will then be written to a registry key value (into HKLM). The issue I'm having is the property is not being updated when written to the registry (writes empty string due to the property being created in the custom action). I think it has to do with the order that the custom action is being executed but I've tried moving the custom action in the sequence chain to an earlier stage (sequence was 99) and that has not worked. I'd like to note the log file shows the property is being updated

Current setup of wix .wxs

<InstallExecuteSequence>
  <Custom Action="CustomActionTest" Before="WriteRegistryValues"/>  
</InstallExecuteSequence>

<Fragment>
  <Binary Id="CustomActionBinary" SourceFile="..\CustomActionTest.CA.dll"/>
  <CustomAction Id="CustomActionTest" BinaryKey="CustomActionBinary" DllEntry="CustomAction1" Execute="firstSequence" Return="check"/>
</Fragment>

<Component Id="CMP_WriteToLicenseRegistry" Guid="{}" Permanent="yes">
  <RegistryKey Root="HKLM" Key="SOFTWARE\Test">
    <RegistryValue Action="write" Name="TestDate" Type="string" Value="[TestDateRegistryValue]"/>
  </RegistryKey>
</Component>

The Custom Action in CustomActionTest.CA.dll

    [CustomAction]
    public static ActionResult CustomAction1(Session session) {
        session.Log("VALUE BEFORE " + session["TestDateRegistryValue"]);
        session.Log("Begin CustomAction1");

        session["TestDateRegistryValue"] = DateTime.Now;

        session.Log("VALUE AFTER " + session["TestDateRegistryValue"]);

        session.Log("End CustomAction1");

        return ActionResult.Success;
    }

Solution

  • The custom action is running in the first sequence and as an immediate (default type) action. This means it will run during the 'client' phase of the msi installer.

    The WriteRegistryValues action is run in the server phase and only has access to properties available in this phase. This includes the default values of properties from the msi database itself and any public properties marked secure.

    To have your property value be available in the server phase you must mark it Secure='yes'. To mark a property as secure it must also be a public property which means it needs to have an all capital name.

    So, you should be able to set your registry value properly if you update your property to be

    <Property Name="TESTDATEREGISTRYVALUE" Secure="yes">
    

    and update the name in the custom action and <RegistryValue> as well.