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

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

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?

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.

Accessing InstallShield Task in MSBuild

I'm trying to use MSBuild to create a target that will create an installer with InstallShield 2012. I'm having difficultly understanding how to access InstallShield. I ran across this mentioning an InstallShield task but I'm not sure how to get access to it. I think I need a UsingTask directive, but not sure what to import. Can someone give me a pointer on how to get this going? Thanks.
You need to import the targets file. Took me a while to figure that out as well since it's in the msbuild extensions directory together with a dll. Here's a basic sample of how to use it (note this is for 2012Spring but you get the idea):
<Import Project="$(MSBuildExtensionsPath32)\InstallShield\2012Spring\InstallShield.targets" />
<Target Name="BuildInstaller">
<InstallShield.Tasks.InstallShield
Project="/path/to/my.ism"
ProductConfiguration="Package"
ReleaseConfiguration="MSI" />
</Target>
Btw if this doesn't work out for some reason, you can always invoke ISCmdBld.exe in an Exec task, it will do the job just as fine.
InstallShield provides Visual Studio integration. When you create an InstallShield project in VS it creates a project file (.ISPROJ) which imports the InstallShield.targets file for that version of InstallShield. The project file contains plenty of examples on how to build a particular configuration and pass in such things as merge module path, properties, path variable overrides and so on.
Please note that building InstallShield requires the x86 MSBuild platform due to COM components.

How can dependencies for a CustomBootstrapperApplication.dll be packaged?

I'm creating a wix burn custom bootstapper application dll.
The installer neeeds to perform some validation before allowing the install to complete. To do this I use a third party dll. When I run the installer exe, I get an error that the dll is missing from my computer. I tried to package it like this:
<BootstrapperApplication SourceFile="$(var.Build.Output)MyCustomBootstrapperApplication.dll">
<Payload Id="ThirdPartyDependencyDll" SourceFile="$(var.Build.Output)ThirdPartyDependency.dll"/>
</BootstrapperApplication>
But, that doesn't seem to work. Is there a way of creating a custom bootstrapper and packaging dependant dlls with it?
Thanks.
The solution I found was to switch the dll to delay link. Then, in BootstapperApplicationCreate, use AddDllDirectory to add the temp path to the process's dll search paths, and then LoadLibraryEx on it with flags specified to get it to search the modified path.

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