Rob Mensching has been promising to put an updated version of WiX with better written documentation on sourceforget.net for a while now. But at the time of writing the May 27th build is still the latest one. But do you know what? I’m beginning not to care. I’m actually getting to the point where I can do anything I want: though the gifts of dark and orca (for examining what’s going on in an msi) and virtual pc for an easy way to test roll outs.
After the epic that was finding out how to ngen stuff as part of an MSI I moved on to trying to automate other parts of our deployment process. This means running the installer classes inside the .NET assemblies. While could have used the same approach as ngen added a CustomAction that called InstallUtil with the correct parameters, I wanted to see if it was possible to call the install classes directly from the MSIs.
I started off with the assumption that if it was possible to call install classes directly from an MSI then this is what visual studio generated MSI would do. Anyway visual studio generated MSI do not call the install class directly, but they don’t make a call to installutil.exe either; so I thought I’d explain here what they do. I guess this doesn’t prove that it isn’t possible to call installer classes directly, so if any one has a way of doing this I’d be interested to here.
While anyone could of course use dark to reverse engineer a visual studio generated assembly for themselves, there are a few little pit falls that make it quite tricky. Also visual studio produced installers look pretty yucky when reverse engineered from dark because of the auto-generated ids. So I thought it might be worth a blog entry anyway.
When visual studio creates an msi with a custom action it embeds 3 binary streams into the binary table. You can use dark with the –x switch to get both the syntax for embedding these and the streams themselves. Below is shown the syntax for adding them to the binary table. These binaries provide a sort of installutil like functionality that can be embedded into the MSI. While only InstallUtil is directly involved in running the installer class, the other two are required as either libraries or to set up some temporary files required by the InstallUtil.
<Binary Id="InstallUtil" src="Binary\InstallUtil.ibd" />
<Binary Id="MSVBDPCADLL" src="Binary\MSVBDPCADLL.ibd" />
<Binary Id="VSDNETCFG" src="Binary\VSDNETCFG.ibd" />
Running the installer class requires two CustomActions tags. One CustomAction sets up a property which will form the parameter to the call to the InstallUtil then the second custom action class actually call the InstallUtil. The syntax is shown below, the most important bit is the Value attribute, get this wrong and the installUtil will throw an error, most likely a cryptic one.
<CustomAction Id="TestInstaller.dllInstall.install.SetProperty" Property="TestInstaller.dllInstall.install" Value="/installtype=notransaction /action=install /LogFile= "[#TestInstaller.dllFile]" "[VSDFxConfigFile]"" />
The "[#TestInstaller.dllFile]" section of the value is arguably the most important bit. The “TestInstaller.dllFile” should be the id of the File tag that contains the installer class you whish to run.
I’ve tried removing the "[VSDFxConfigFile]" section as I couldn’t work out where this was coming from, an therefore thought it was wall dressing. But the InstallUtil will not work with out it. The properties value is actually set up by the custom action shown below.
<CustomAction Id="SetPrereqs" BinaryKey="MSVBDPCADLL" DllEntry="CheckFX" />
The custom action that actually runs the InstallUtil is given below. The one thing that slightly unclear to me is why the parameter created in the TestInstaller.dllInstall.install.SetProperty is passed to the InstallUtil. I’m guessing that it’s because the CustomAction and the Property share the same name, but I’m not completely sure.
<CustomAction Id="TestInstaller.dllInstall.install" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
And that about it, the rest is stuff I’ve coved before. I’ve gone to town on the example, there is a c# source file included that creates a .dll with an installer class, so the wxs source file should compile, link and run no problem.