Registering COM EXE with WIX - wix

I created a solution with two new projects: ATLProject1 which is a COM dll and ATLProject2 which is a COM EXE. To both projects added same simple class with single method.
Added both to WIX setup project (this is an existing setup project that already installs other COM dlls. I'm just using it for this test).
Added following lines to product.wxs:
<Component Id="ATLProject1.dll" Guid="{...}">
<File Id="ATLProject1.dll" Name="ATLProject1.dll" KeyPath="yes" SelfRegCost="0" Source="$(var.TargetDir)\ATLProject1.dll" />
</Component>
<Component Id="ATLProject2.exe" Guid="{...}">
<File Id="ATLProject2.exe" Name="ATLProject2.exe" KeyPath="yes" SelfRegCost="0" Source="$(var.TargetDir)\ATLProject2.exe" />
</Component>
and also
<ComponentRef Id="ATLProject1.dll" />
<ComponentRef Id="ATLProject2.exe" />
The file also has these lines:
<EnsureTable Id="PublishComponent"/>
<EnsureTable Id="Condition"/>
<EnsureTable Id="TypeLib"/>
<EnsureTable Id="Class"/>
<EnsureTable Id="Extension"/>
When running the setup I get error: "Module ATLProject2.exe failed to register. HRESULT -2147024769" (hex 0x8007007f the specified procedure cannot be found).
If I remove ATLProject2 from setup, it succeeds and ATLProject1 is correctly registered in registry (this is without generating registry information e.g. using heat, it just works).
Should exe component be treated differently?
I found this 10 year old post suggesting heat.exe does not treat COM exe as COM. If this is the problem, Not sure if this is still the case?

The Windows Installer does not recommend using SelfReg to register at install time. Instead, adding the registration to your .wxs code or capturing the registration at build time is highly recommended.
To add the registration manually, you don't use EnsureTable, you use the COM related elements (like Class, ProgId, TypeLib). It can be tedious but will be far more robust than trying to selfreg during installation.
Unfortunately, the alternative to capture the registration during build using heat.exe (provided in the WiX toolset) does not support capturing from executables. If you are open to a commercial solution, we (FireGiant) developed an alternative to heat.exe that can capture executable registration (and much more). That advanced harvesting solution has more documentation on the FireGiant site.

RegServer Switch: COM EXE files are normally self-registered via the /RegServer switch as in:
MyBinary.exe /RegServer
In other words EXE files are not registered via the normal regsvr32.exe mechanism. This is the tool used to register COM dll's and OCX files, but it does not handle EXE files. There is also an /UnRegServer switch to unregister EXE COM files - for the executables that support /RegServer (which is not all COM EXE files - it could be missing as a feature).
Self-Registration: Self-Registration is not ideal to register COM files, and here is a write-up of why this is the case: MSI register dll - Self-Registration considered harmful. In MSI one extracts the COM registry data and populates a number of special COM-tables to allow the registration of the COM server in a way that supports advanced features such as rollback. I don't like the COM extract either (risk of self-repair problems, more on self-repair problems), but it helps in most cases - especially when there are dependencies that can trigger registration problems. Moreover it is the way COM files are supposed to be registered in MSI. It is the standard. I should note that some COM settings go into the Registry table still - since there are no dedicated COM-related tables for them.
heat.exe: WiX's own heat.exe tool now can extract COM data from dll files and ocx files (32-bit). But it does not seem to work for EXE COM files - I am not sure why:
heat.exe file MyCOMDll.dll -out MyCOMDll.wxs
RegSpy2.exe: There is a tool you can use to extract COM registration information from both DLL, OCX and EXE files. It can be downloaded from here: http://www.installsite.org/files/iswi/RegSpy2.zip. Here is the main page listing numerous tools. The RegSpy tool is written by Phil Wilson - MSI Expert and author of The Definitive Guide to Windows Installer (APress).
Here is how to extract the COM data from a COM executable (if you get no data, try unregistering the file first and then running regspy.exe):
RegSpy.exe MyBinary.exe /RegServer >> RegistryOutput.reg
The exported *.reg file can then be converted to WiX elements. This is not an easy process. Using the WiX tool heat.exe does not populate the proper COM tables, but rather puts everything in the Registry table (which will work though, barring MSI validation errors):
heat.exe reg MyCOMRegistryData.reg -out MyWiXFile.wxs -sfrag -suid
There used to be a tool called Tallow that converted reg files to WiX COM registration, but this tool is no longer anywhere to be found. I am not aware of any other ways to generate it short of writing it yourself, or download another deployment tool and import the COM data or extract it and decompile the generated MSI with dark.exe and take out the WiX markup. Or figure out how heat.exe writes its WiX XML output with COM data and adapt that to process the output from RegSpy.exe.
UPDATE: Throwing in a link to Paraffin: https://github.com/Wintellect/Paraffin. This is supposedly a "better Tallow". I am not sure what it supports in terms of COM-extract. My quick test seemed to indicate it doesn't support COM extraction at all, but supports auto-generating WiX markup and add and remove files for updates.
Custom Actions: It is possible to register your COM EXE by means of a custom action that calls the /RegServer switch as well, though this is not recommended for all the reasons listed in the link above (self-registration considered harmful).
Some Links:
Adding a .reg file to registry WIX
How to generate WiX XML from a .reg file?

Related

How to extract MSVC rutime libraries from merged `Microsoft_VC141_CRT_x64.msm` during setup verification

Background
I have complex C++ application which is installed using msi installer (defined with wix).
My application need MSVC run time libraries so Microsoft_VC141_CRT_x64.msm is merged to my installer.
<DirectoryRef Id="APPDIR">
<Merge Id="M.visualStudioRuntime" Language="0" SourceFile="$(var.DependenciesPath)/Microsoft_VC141_CRT_x64.msm"
DiskId="1" />
</DirectoryRef>
....
<FeatureRef Id="F.SomeComponent">
....
<MergeRef Id="M.visualStudioRuntime" />
</FeatureRef>
Now during installation process some data on remote server have to be verified. For that task, I'm extracting my application dll to temporary folder, loading library and execute some function with required parameters. Depending on outcome installation setup is allowed to continue or not.
This dll depends on third party (ok not fully third party it comes from other team) C++ library which also uses MSVC run-time so static linking is not acceptable solution.
Problem
When I'm loading my application dll from temporary folder it needs those MSVC run time libraries. To do that I need exact those dlls to this temporary folder.
Problem is observed only on Windows 2012, other supported Windows versions have this run time preinstalled.
Question
What is best way to extract those MSVC runtime libraries to temporary folder?
Notes
I've inherited this installer and current implementation manually embeds those dll (as duplicates) in installer extract them based on predefined id. This is bad solution and I wish need to fix it properly.
C++: Are you running a C++ custom action that needs those runtimes? Try to statically link as explained here - then there is no need for the VCRuntime files. If you are not running C++, please let us know.
Inlined Essence: Project settings => C/C++ => Code Generation => Change the runtime library setting to multithreaded instead of multithreaded dll.
Custom Action Tips: Here is an answer on common C++ custom action problems: Interrupt installation when custom action returns error.
Secondary Answer: To extract files from a merge module, the easier approach is to add it to a project, build an MSI and then run administrative installation on the MSI - which is a glorified file extraction from the MSI: What is the purpose of administrative installation initiated using msiexec /a?
Basic Command:
msiexec.exe /A MySetup.msi

Should the installed entry in the registry be in the Microsoft folder?

When adding a shortcut to an installer created with Wix, according to How To: Create a Shortcut on the Start Menu, you need to add a registry value with like this:
<RegistryValue Root="HKCU" Key="Software\Microsoft\MyApplicationName" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
Should that value really be inside of Software\Microsoft? In many cases in the Microsoft world I'm seeing the vendor used as the scope so I'm wondering if it shouldn't really be Software\MyVendorName\MyApplicationName.
I would definitely write to my own location as indicated by others:
HKCU\Software\MyVendorName\MyApplicationName
HKLM\Software\MyVendorName\MyApplicationName
Ideally your application should not write anywhere else in the registry - except beneath these two parent locations. You "own" these two registry locations - and nowhere else. You shouldn't write anywhere else - and certainly not under the Microsoft key. I believe that is a "generic sample".
The exception is when you need to register certain files (or components) - for example COM files whose registration go into HKLM\SOFTWARE\Classes and HKCU\SOFTWARE\Classes. These per machine and per-user locations are merged to produce HKCR (HKEY_CLASSES_ROOT). COM registration can also be isolated, in which case you use manifest files - then the registry is not involved at all. WiX features special COM-related elements that will populate the registry for you via standard MSI mechanisms - the heat.exe tool for harvesting COM registration (among other things) will auto-generate these elements for you and your compiled MSI will have several MSI tables keeping the COM registration information (ProgId, Class, TypeLib, etc...).
UPDATE: Not to compliate things too much, but an MSI can be installed per-user or per-machine based on the values of ALLUSERS and MSIINSTALLPERUSER properties. If you have populated the proper COM tables in the MSI the COM server will be registered per-machine or per-user accordingly.
And there are other cases where installation processes make changes elsewhere in the registry if you install your package. For example when you install drivers, plug-ins, fonts, COM+, COM Interop, file extensions, etc... Your registration in these cases should generally go through APIs that take care of registering your components and you should not poke around i the registry yourself in most cases. A lot of such registration is handled by MSI if you do it right - or built-in constructs in third party tools used to make MSI files.

How to work with HEAT.exe for dll registry

and i need to register a dll . Right now am registering the dll as below
<CustomAction Id='comReg' Directory='INSTALLLOCATION' Impersonate='no' Execute='deferred'
ExeCommand='"[NETFRAMEWORK40CLIENTINSTALLROOTDIR]regasm.exe" "[INSTALLLOCATION]myProduct.dll" /codebase' Return='check' />
but all are suggesting to use HEAT.exe in internet wherever and whenever i surf . I even have gone through this link. But there they have only the syntax etc. I really dont know how to work with it just by knowing those syntax.
I need some step by step procedure or some good blog which elaborately tell how how to harvest a dll and how to impllement it in to wix code and how the registry will be done , so that i can register my dll based on conditions also.Even i tried this link alse
Regards
Registering a COM component is done through standard Windows Installer actions and tables. Numerous table entries are required so WiX provides heat.exe to harvest COM files. It works by inspecting a file for type libraries and, if the DllRegisterServer entry point is present, running it in a Registry sandbox where changes are intercepted and captured. (In the era of Windows Installer [1999-present], DllRegisterServer is effectively deprecated for any other purpose.)
As you may know, a Feature is the smallest user-selectable unit of installation. A Component is a member of one or Features in one or more Products. Heat creates a component for each file it harvests and a ComponenentGroup for each harvest run. So, you have to pick a ComponentGroup Id and reference it in one or more Features. You also have to pick a Directory Id for the destination of the ComponentGroup.
Now, it is simply a matter of editing your project file to harvest the file. To edit a project file you could use a text editor but Visual Studio is all set up for it. See How to: Edit Project Files.
Add a HarvestFile element to a new or existing ItemGroup, entering the desired ComponentGroup Id and Directory Id
<ItemGroup>
<HarvestFile Include="comserver.dll">
<ComponentGroupName>COM</ComponentGroupName>
<DirectoryRefId>ServerDir</DirectoryRefId>
</HarvestFile>
</ItemGroup>
In your Product.wxs or elsewhere, add a ComponentGroupRef to one or more Features.

Controlling Codebase registry entries in heat-generated WiX fragments

I have a .NET 4.0 assembly that needs to be made COM-visible during installation. I'm using WiX (version 3.5), so generating a WiX fragment with heat is the logical option. This works fine, except no matter how I twiddle the knobs on heat, the CodeBase RegistryValues default to "file:///C:/Windows/Microsoft.Net/assembly/GAC_32/..." while the assembly is most certainly not installed in that directory.
The registry entries are added correctly during installation, but point to a non-existent assembly. Sad day. I have this issue even in the simplest possible use case ("heat asm.dll -out asm.wxs").
The options seem to be:
Handle installation of the assembly elsewhere in the WiX project, then manually modify the CodeBase declarations in the fragment before passing it to the rest of the WiX toolchain.
Manually add an Assembly=".net" attribute to the file tag
(http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/net-COM-registration-with-heat-td3606182.html)
Transform the fragment with XSLT (2010-06-03 Accentient Blog “Adding HEAT output to the GAC”)
None of these options are particularly appealing. Is there an automated way to do this that doesn't involve fiddling with XSLT?
Does registration-free COM activation meet your requirements?
Registration-Free Activation of COM Components: A Walkthrough
http://msdn.microsoft.com/en-us/library/ms973913.aspx

Register ActiveX exe server using WiX

I have several VB6 ActiveX server exe files which need to be registered on install before they can be used.
I have tried using Heat to extract the information but it only generates a file element.
These files can be registered by calling them with the /regserver switch and unregister by calling them with the /unregserver switch. I understand this is not the correct way to this. Instead I should add the registry keys and other required elements to my wix source.
My question is how do I find out what registry keys and other element I require to register these ActiveX exe files. Seeing as Heat seems unable to harvest this information.
how do I find out what registry keys
and other element I require to
register these ActiveX exe files
In general, you can discover registry changes like this:
Bring the registry in a clean state,
e.g. use myapp.exe /unregserver
Create a dump of the registry
content like this
c:\WINDOWS\system32\reg.exe export dump1.reg
Run the command that will change the registry, e.g. myapp.exe /regserver
Create another dump2.reg of the
registry.
Find the differences between
dump1.reg and dump2.reg with a
diffing tool (e.g. TortoiseSVN
adds a "diff" command to the
explorer context menu when you have
two files selected)
There might be some noise in the differences that you should ignore. A typical example is HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\RNG\Seed. This registry key is used by the windows CryptoAPI to store continuously gathered entropy. Incidentally, this key sometimes shows up in MSI packages generated by commercial setup generators. This seems to indicate that they use a similar registry-sniffing technique :-)
I had the same problem with tallow from WiX 2.0 and had to implement registry harvesting for out-of-proc servers. Here is the patched tallow. Would be nice to merge the ProcessWithInjectedDll class to Heat and probably converge to the main trunk at some point.
Beware that lots of cruft from VB6 runtime gets in the generated registry keys. The generated output is unusable without some tweaking. That's when CleanupRegInclude.vbs can be useful.
Last but not least, absolute filenames and paths are useless. You have to use #YourComponent and $YourComponent instead (check the MSI documentation).
ActiveX controls are just COM objects. The minimum amount of registration you need to do is something like this:
<RegistryKey Root="HKCR" Action="createAndRemoveOnUninstall" Key="CLSID\{YOUR-GUID-HERE}">
<RegistryKey Action="createAndRemoveOnUninstall" Key="InprocServer32">
<RegistryValue Action="write" Value="[INSTALLDIR]YOUR-DLL-HERE.dll" Type="string"/>
<RegistryValue Action="write" Name="ThreadingModel" Value="Apartment" Type="string"/>
</RegistryKey>
</RegistryKey>
You may want to register a Prog ID:
<RegistryKey Action="createAndRemoveOnUninstall" Key="ProgID">
<RegistryValue Action="write" Value="YOUR.PROGIDHERE" Type="string"/>
</RegistryKey>
I thought heat.exe had been updated to be able to harvest COM EXE files, but I guess it might not have been implemented yet.
I normally use a tool called RegSpy / RegSpy 2 to extract COM info from DCOM EXE files: http://www.installsite.org/pages/en/tt_analyze.htm#RegSpy.
Using the above tool will give you a reg file, but you will still need to convert to WIX format. To get the reg file you go:
regspy2.exe myfile.exe >> myfile.reg
I don't think there is a way to automatically convert a reg file to wxs format (I remember writing a basic converter a while ago, but don't have it here). To make this easy you can extract the info required using Installshield or Wise For Windows Installer, build an MSI and then disassemble the msi to Wix format using the dark.exe (wix decompiler). The resulting Wix markup can then be added to your project.
I tried both heat and the regspy mentioned by #Glytzhkof but found that neither did a complete extract of all the relevant registry info for my COM server. I did however find a utility - RegSpyUI - that sort of ships with InstallShield which did a lovely job. Described in more detail here.