Donahue, Crash Scene Investigator

Red Gate Support Engineer

Arrrrgh! Wix!

Published Tuesday, October 21, 2008 6:56 PM

This week's time-eater, for me, was to try to create an installer package (MSI) with custom actions that install databases on SQL Servers. Typically, I had grown to like Microsoft Visual Studio Deployment Projects, because I could easily knock out some C# code and slam it into an installer and get it to do, basically, anything I want.

A few days ago, though, all I had at my disposal was Mister Pokey, the Little Computer That Couldn't. Since Mister Pokey is less than gifted in the processor department, all he runs is the "Express" version of Visual Studio. It's nice for sticking together little projects, writing a little puzzle game, and things like that, but it is minus the Deployment Project Wizard.

I remember some developers telling me that VS Deployment is for girls, and the manly-man programmer type uses WIX, you know, because it's bl**dy difficult to understand, which makes them feel all better about themselves, or something. How hard could that be? Well, it's not entirely obvious how to use it.

To make a long story short, you'll need to know installers inside-and-out before you can attempt to compile a WIX installer. There is no UI (well there is Votive, which I haven't tried out), and the documentation isn't brilliant. But on the plus side it is a gimmie and allows for incredibly fine-grained control.

If you do want to deploy an existing Windows Installer class that you had created using the VS deployment project in WIX, this is a hard-won battle, but possible. Even though the author of WIX is dead against it and every Installer Jockey at Red Gate tells me that managed installers cause grief and famine and cataclysm beyond imagination. Just to irk them, here is the code. If you want to know how to get these .ibd files, what you basically have to do is reverse-engineer one of your existing VS deployment MSIs using Orca. Actually you could use WIX (dark -x <msiname>.msi, to be specific) but I couldn't get that going. I used Orca to export the Binary table of my old installer and plopped the whole mess into a subfolder called "Binary".

<?xml version="1.0" encoding="utf-8"?>
<
Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
<
Product UpgradeCode="79C0A2EF-7A27-4227-9323-376F8D643C42" Name="Packager Test" Id="4AD025EB-922B-44E1-84B6-B5CC05F19A00" Version="1.0.0" Manufacturer="Brian Donahue" Language="1033">
<
Package Id="C83C3011-4205-40AA-8E0B-4106A33E9391" Manufacturer="Brian Donahue" InstallerVersion="200" Platforms="Intel" Languages="1033" Compressed="yes" SummaryCodepage="1252" />
<
Media Id="1" EmbedCab="yes" Cabinet="Test.cab" />
<
Binary Id="InstallUtil" src="Binary\InstallUtil.ibd" />
<
Binary Id="MSVBDPCADLL" src="Binary\MSVBDPCADLL.ibd" />
<Binary Id="VSDNETCFG" src="Binary\VSDNETCFG.ibd" />

<Directory Id="TARGETDIR" Name="SourceDir">
<
Directory Id="TestDir" Name="Test">
   <
Component Id="TestInstaller.dllComponent" Guid="2B6D1187-9DBC-7A6F-B9ED-E6AD9DD6D248">
<
File Id="PkgInstaller.dllFile" Name="SQLPAC.dll" LongName="SqlPackagerDeployment.dll" Vital="yes" KeyPath="yes" DiskId="1" src="SQLPackagerDeployment.dll" />
<
File Id="BaselinePackage.exeFile" Name="SQLPAB.exe" LongName="SQLPackagerBaseline.exe" Vital="yes" DiskId="1" src="SQLPackagerBaseline.exe" />
<
File Id="UpgradePackage.exeFile" Name="SQLPA1.exe" LongName="SQLPackagerUpgrade1.exe" Vital="yes" DiskId="1" src="SQLPackagerUpgrade1.exe" />
</
Component>
</
Directory>
</
Directory>

<Feature Id="DefaultFeature" Level="1" ConfigurableDirectory="TARGETDIR">
   <
ComponentRef Id="TestInstaller.dllComponent" />
</
Feature>

<CustomAction Id="SetPrereqs" BinaryKey="MSVBDPCADLL" DllEntry="CheckFX" />
<
CustomAction Id="TestInstaller.dllUninstall.uninstall" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
<
CustomAction Id="TestInstaller.dllUninstall.uninstall.SetProperty" Property="TestInstaller.dllUninstall.uninstall" Value="/installtype=notransaction /action=uninstall /LogFile= &quot;[#PkgInstaller.dllFile]&quot; &quot;[VSDFxConfigFile]&quot;" />
<
CustomAction Id="TestInstaller.dllInstall.install" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
<
CustomAction Id="TestInstaller.dllInstall.install.SetProperty" Property="TestInstaller.dllInstall.install" Value="/installtype=notransaction /action=install /LogFile= /SERVER=localhost /DATABASE=SqlPackagerExample &quot;[#PkgInstaller.dllFile]&quot; &quot;[VSDFxConfigFile]&quot;" />
<
InstallExecuteSequence>

<Custom Action="SetPrereqs" Before="AppSearch" />
<
Custom Action="TestInstaller.dllUninstall.uninstall.SetProperty" After="MsiUnpublishAssemblies">$TestInstaller.dllComponent=2</Custom>
<
Custom Action="TestInstaller.dllUninstall.uninstall" After="TestInstaller.dllUninstall.uninstall.SetProperty">$TestInstaller.dllComponent=2</Custom>
<
Custom Action="TestInstaller.dllInstall.install.SetProperty" After="SetPrereqs">$TestInstaller.dllComponent&gt;2</Custom>
<
Custom Action="TestInstaller.dllInstall.install" After="TestInstaller.dllInstall.install.SetProperty">$TestInstaller.dllComponent&gt;2</Custom>
</
InstallExecuteSequence>

</Product>
</
Wix>

Now we can compile the WIX script using the very intuitive tools that come with it. And by "intuitive" I mean "batch file". The file above has been named "DBInstaller.wxs".

@Echo please ensure candle, light and csc are on the path!
del /Q output\*
rmdir output
mkdir output
..\candle DBInstaller.wxs /out output\DBInstaller.wixobj
..\light output\DBInstaller.wixobj /out output\DBInstaller.msi
msiexec -lv* output\log.txt -i output\DBInstaller.msi

What this WIX package does is to run a very simple installer with no UI. On Install, the SQLPackagerDeployment.dll is used with the arguments /SERVER=localhost and /DATABASE=SqlPackagerExample. You have to be very careful about the order of the arguments... whatever you do, the last two arguments to the CustomAction value have to remain intact! $TestInstaller.dllComponent=2  makes the custom action run only when uninstalling, and >2 makes the custom action run only when installing.

   Of course, since managed installers will cause a rift in the space-time continuum, I have re-implemented the whole thing in VBScript. I'm saving that story for later!

Comments

 

mjswart said:

I remember my own frustrations with WIX.
ORCA was invaluable
and so was the Windows Installer reference here
http://msdn.microsoft.com/en-us/library/aa372860(VS.85).aspx
October 21, 2008 2:19 PM
 

intel cpu comparison chart games | Bookmarks URL said:

October 22, 2008 6:28 AM
 

DuncanSmart said:

MSI/Windows Installer is a over-complicated disaster. I hate the way your machine grinds away when running a tiny 2MB MSI setup. Supposedly MSI is doing clever stuff so that the install is transactional but the number of times a machine has been had to be re-paved due to some Windows Installer database corruption...

Stick with simple stuff like InnoSetup or NSIS for setups. How hard does it have to be? Copy some files, add some registry values, run a custom process. If your setup has to be any more complicated than that, you're doing it wrong.

I totally agree with this: "The odds of me trying out your utility are inversely related to whether it packaged in an MSI" http://twitter.com/kevindente/status/972830502
October 24, 2008 9:41 AM
 

Brian Donahue said:

Ultimately my goal is to install a SQL Server database directly from an MSI. As far as I can tell, this requires writing custom actions and hitting the "bare metal" of the Windows Installer technology. If it were a matter of slapping down some files and tweaking some registry entries, Wix has some mighty fine pre-made UI templates that aren't that hard to use, so I won't criticise Wix too harshly.

It just seems that Installer itself needs to sprout some more useful standard actions, so that users don't spend so much time plugging in custom actions. Most  MSI standard actions don't add any value to installing .NET products, and database installation seems to be completely overlooked!
November 4, 2008 5:43 AM
You need to sign in to comment on this blog

















<October 2008>
SuMoTuWeThFrSa
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
A SysAdmin's Guide to Change Management
 In the first in a series of monthly articles, ‘Confessions of a Sys Admin’, Matt describes the issues... Read more...

Exchange: Recovery Storage Groups
 It can happen at any time: You get a request, as Admin, from your company, to provide the contents of... Read more...

Build Your Own Virtualized Test Lab
 Desmon explains the fundamentals of building a test lab for Windows servers and Enterprise applications... Read more...

Rendering Hierarchical Data with the Treeview
 It sometimes happens that Web Server controls that visualize data don't quite fit with the way that... Read more...

SQL Server 2008: Performance Data Collector
 With Performance Data Collector in SQL Server 2008, you can now store performance data from a number of... Read more...