Search code examples
wixregsvr32

Running regsvr32 as part of a WIX installer


I have authored a COM component that is distributed through a WIX-generated MSI.

The COM component has rather complicated and non-static registration logic which means that embedding the registration information directly in the Windows Installer WXS file is not a feasible option - registration must be done using regsvr32 - and it's a 32-bit COM component, so it must use the 32-bit version of regsvr32.exe - that is %SystemRoot%\SysWow64\regsvr32.exe on 64-bit Windows or %SystemRoot%\System32\regsvr32.exe on x86 Windows.

I noticed two problems with WIX with this WXS XML:

<InstallExecuteSequence>
    <Custom Action="COMRegister"   After="InstallFinalize">NOT Installed</Custom>
    <Custom Action="COMUnregister" After="InstallInitialize">Installed</Custom>
</InstallExecuteSequence>

<CustomAction Id="COMRegister"   Directory="APPLICATIONROOTDIRECTORY" ExeCommand='regsvr32.exe /s "[APPLICATIONROOTDIRECTORY]Component.dll"' />
<CustomAction Id="COMUnregister" Directory="APPLICATIONROOTDIRECTORY" ExeCommand='regsvr32.exe /s /u "[APPLICATIONROOTDIRECTORY]Component.dll"' />
  1. The wrong regsvr32.exe was being invoked. I noticed that the x64 version of resgvr32.exe was being run on 64-bit systems instead of the 32-bit version.
  2. regsvr32.exe was being run without elevated permissions, so COM registration failed with E_ACCESSDENIED.

For 1. it works if I hardcoded the path to the regsvr32.exe executable using [WindowsFolder]\SysWOW64\regsvr32.exe, but this wouldn't work on a real 32-bit machine where SysWow64 doesn't exist.

For 2. I read online that changing After="InstallFinalize" toAfter="RemoveExistingProducts"would cause it to run with elevated permissions, however instead this just gives me errors aboutRemoveExistingProducts` being an unresolved symbol name.

How can I resolve these two issues?

Update

(After struggling with this problem for the past 2 hours, I'm convinced the authors of WIX are close relations of H.P. Lovecraft)

I've worked-around the first issue by writing my own intermediate-step program which is a 32-bit executable, so it will always run under a WOW context, so it will reliably invoke the 32-bit regsvr32.exe program.

I found out the issue with the second issue was these things: For a CustomAction to run with elevated permissions (well, in the same security context as the main installer job) these conditions must be true:

  1. <Custom/>" must haveBefore="InstallFinalize", and **not**After=""any other values forBefore=""` won't work reliably as WIX or Windows Installer might rearrange the actions (wut).
  2. <CustomAction /> have have these attributes explicitly set:
    • Execute="deferred"
    • Impersonate="off"

Even-so, I would like to not have to use my helper program to correctly resolve the 32-bit regsvr32.exe. What options are there?


Solution

  • I wouldn't advise using self registration at all it is not the really the right way to do it with Windows Installer, if you really must set File/@SelfRegCost to 1.

    A much better way is to extract the registry values and write them with WiX - you can also use heat to generate the values.