Wix Bind Substring or Split - wix

I'm trying to get a Wix installer written that does some TypeLib registration.
I'm already pulling the FileVersion off a registered file elsewhere using
!(bind.FileVersion.#InteropDll)
but I want to do the same thing for the TypeLib, which only has separate MajorVersion and MinorVersion attributes. Ideally, I'd like to do
<TypeLib ...
MajorVersion="!(bind.FileVersion.InteropDll).Split('.')[0]"
MinorVersion="!(bind.FileVersion.InteropDll).Split('.')[1]">
How can I accomplish this (or the like)? ...Or should I just not bother with all this and invoke regasm on the dll file at install time?
Thanks.

The WiX toolset doesn't support doing that today. It's an interesting feature request. I would never call regasm during an install. It's way to hard to get rollback and patching and all that working correctly by shelling out to an external executable.

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 bootstrapper, global install directory

I have an application with a bootstrapper that installs multiple components below it. The code below uses ninject to have a loosely coupled database layer.
With regards to the bundle/bootstrapper, I would like to move the database layer out into a separate msi in order to support optional data layer choices on install (e.g.: radio buttons to install SQLite/SQLExpress/MySQL etc..).
I am struggling to figure out how to get the install directory working though, as the database components needs to install into the root/install directory of the main application. (rather than using the gac etc).
How can I do this? I have tried the steps mentioned here: How to use properties to set the installation path? but to no avail. I must have something wrong.. but given the code is spread over 5(ish) files, it seems a little large to load here!
Any pointers to get started trying to implement this, or should I go ahead and upload the code?
The method you refer to should work. Note however that the name of the property given in
<MsiProperty Name="INSTALLLOCATION"
should match the name used in wxs file of the corresponding MSI package. Typically if the MSI was created based on WixUI_InstallDir template the name would be APPLICATIONFOLDER and in the default template without the UI it is INSTALLFOLDER.

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.

WiX Bundle with dynamic MsiPackage names

I'm converting our current monolithic installer to use a WiX 3.7 Bundle/chain. We have several components that are now building into their own separately-maintainable MSI installers. My next task is to add all of these to a bootloader/bootchainer, but I've hit a snag.
A requirement for our individual installers is that they contain the version in the filename (i.e. MyApplication-5.4.22.msi). I don't see a tool like Heat for collecting MSI packages together, and I don't see a way to add an MsiPackage element with a wildcard to account for varying package names.
As a last resort, I can wrap the bundler inside of another MSBuild script that will 'autocomplete' the filenames and pass the paths in as variables to the bundler. I'm hoping someone can recommend a solution that works directly in the wxs or wixproj setting.
If the msi files are built with WiX Setup projects, the WiX Bootstrapper project can reference them, thereby creating useful WiX variables that are defined as the paths to the msi files.
See my answer here, as well as the list of variables here.
If that's not the case then you can write some MSBuild targets that run before the Build target to figure out the actual file paths. If the available standard and community MSBuild tasks aren't sufficient, you can write your own tasks, either by creating an assembly or using inline code. (And, of course, there is always the Exec task to shell out to a command-line program like cmd.exe, after which you can parse its output to extract the msi paths.)

WiX SQL Install

SQL Programmers:
I need to see how you used WiX to execute a collection of SQL files to the server. The files are to be specified in a separate fragment, auto-generated by heat.
The installer does not need to install these SQL files on the target machine, just execute them. (However it would not be a problem if they were installed.)
I also would like to see the error messages (logs) from these executions if possible. I don't see any logging functionality in the WiX SqlExtension.
For starters, I'm trying to use Neil Sleightholm's idea, because it provides logging. Then extend that to dozens of files from heat.
Thanks!
I would use the SqlScript element in the WiX toolset instead of sqlcmd.exe. Heat.exe will not be able to generate all this for you, you'll need to author the SqlScript elements by hand.