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

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.

Related

Registering COM EXE with 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?

WIX/MSI setup writes to HKLM despite MSIINSTALLPERUSER=1

I try to create a MSI Single Package using WIX (3.10). The user can select in the UI whether the package should install Per-User or Per-Machine. The package is initialized with ALLUSERS=2 and MSIINSTALLPERUSER=1. I did not set an InstallScope, as this would limit the Package to one or the other.
If the user selects Per-Machine the setup continues with ALLUSERS=2 and MSIINSTALLPERUSER="". - Everything works as expected.
If the user chooses Per-User installation ALLUSERS=2 and MSIINSTALLPERUSER=1 remain unchanged. If a non-privileged user runs the setup everything works as expected as well.
But if a privileged user executes the setup and chooses Per-User installation, registry keys that should be written to HKCU\Software\Classes\ are still written to HKCR / HKLM\Software\Classes\. This happens without UAC being invoked.
I observed this behavior on a Windows 8.1 (current patch level).
This is not what I want. If the user selects Per-User installation, there should be nothing written to HKLM/HKCR.
Here is sample from the wxs-file:
<Component Id="MyRegistryComponent" Guid="{99999999-9999-9999-9999-999999999999}">
<RegistryValue Id="MyRegistryComponent_MainKey" Root="HKCU" Key="Software\Classes\myapp.myclass" Value="myapp.myclass.foo" Type="string" />
</Component>
I checked the MSI with Orca. This RegistryValue has Root=1 in the Registry table of the MSI.
I tried/checked already:
I verified that the ALLUSERS and MSIINSTALLPERUSER properties are
indeed set as stated above.
I tried setting ALLUSERS="" MSIINSTALLPERUSER=1 – No effect.
I changed Root="HKCU" to Root="HKMU" in the wxs.
This results in Root=-1 in the MSI, but I does not change the final
result after installation.
What am I missing here?
Is possible that this behavior is caused by previous incomplete (un-)installations?
When you say "This results in Root=-1 in the MSI, but I does not change the final result after installation." it's not clear which of the results you're referring to but:
HKCU will always go to HKCU, HKMU is what you need to switch between HKCU and HKLM in a single package setup. So using HKMU and producing a verbose log would be useful to see if there is a failure somewhere in there.
You will get changes in HKCR. That's usually the normal behavior because as this article explains:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx
Quote "The HKEY_LOCAL_MACHINE\Software\Classes key contains default settings that can apply to all users on the local computer. The HKEY_CURRENT_USER\Software\Classes key contains settings that apply only to the interactive user. The HKEY_CLASSES_ROOT key provides a view of the registry that merges the information from these two sources. HKEY_CLASSES_ROOT also provides this merged view for applications designed for previous versions of Windows."
HKCR is a virtual view that combines class registration for the current user with class registration for the machine to present a view of all class entries on the system. Other accounts (such as the system account) will see only HKLM, so what you see exactly depends on who you are.
I suggest that is what is needed here is a test case that uses HKMU as is required, and maybe post that test case. Keep in mind that seeing HKCR entries is normal, going by the documentation, so maybe that explains all that you are seeing.

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.

Custom Action with regsvr

I would like to run a custom action on a dll during my installation process.
There is no clean description that I found. So how would you implement this command:
regsvr32.exe /c /n /i:"[PathToIncFolder]" "[BIN]MyFile.dll"
in Wix during the Installation or maybe degister during uninstall?
Preferrably not. The recommended way to install COM components nowadays is to manually add the registry entries.
You definitely should be performing manual registration of the keys and values needed to install the COM component. The reason self-registration is frowned upon is because of problems concerning rollback and uninstall.
The OLE/COM specification should give you information on what keys need to be registered but at a minimum you will need to add a set of entries to a new subkey at HKCR\CLSID\.
Inside this subkey you will need at a minimum, the path to the component and the threading model.
Depending on what your COM component does you may also need to register a PROGID, file-extension maps and APPID.
If the COM object is a managed assembly then your task is slightly different as you need to refer to the .NET bootstrap assembly instead of your own.
If your COM object is written in ATL then your project probably contains a .rgs file which contains all the registry information you'll need.
For further information on COM registry entries check the MSDN here.

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.