Friday, February 18, 2011

Building Windows installer with WiX

WiX is Windows Installer XML (WIX) Toolset. It's an open source project coming from Microsoft. Actually, it was the first project that Microsoft has officially published under Open Source license. Initially it appeared on SF.NET, but recently has moved to Microsoft's owned Half of the internet still points to SF though.

This tool let's you pack a bunch of files into a user-friendly MSI installer, including GUI, silent install, repair, windows registry editing and Start menu customizations.

WiX is a bunch of cool ideas. The first one goes with the each tools names. There's Heat, Candle and Light. They act as preprocessor, linker and compiler. So no matter whether you know everything about compilers, or you always left it to the IDE - tools seem friendly from the very first look.

As name says it, the spine of the toolset is XML. To turn on the heat, developer needs to specify files to install, user interface, user interactions, install steps, resources and custom actions. All this lands in one or more XML documents following provided XML Schemas.

Microsoft Visual Studio users are lucky, as there's GUI in VS that hides WiX to some extent. However I'm not sure how much flexible it is, i.e. how far can you go without having to manually edit XMLs. I was working on plain XML file in Eclipse IDE. Thanks to XSD Eclipse was able to provide content assist. This saved me from many typo-like bugs and helped find right tags faster, than by looking at the docs.

The installer to build had some requirements. It had to be good-looking, native user experience. Some 3rd-party artifacts needed to be installed in the system as well: a dll, another product msi, and an exe to invoke in install time.

User interface
Installers are typically wizards, built of couple of pages. WiX provides several default pages for standard operations. They're easily customizable with some space for branding. Unfortunately some predefined pages look bad. For example features selection dialog uses ugly drop-downs, rather than checkboxes. Maybe it's useful in some scenarios, but for 99% cases they're confusing.
Those not happy with default GUIs can implement their own by putting basic widgets (Button, Text, Label) together. All in XML. That's a bit of work for a beginner who previously built GUIs only in HTML or Java. There are also little caveats here and there, that can turn simple changes into a whole day of work. For example, there's no support for transparent background in checkboxes, or background color is different on various Windows versions. So good luck, if you're planning for many customizations.

Overall, user interface looks nice. It's simple, minimal, doesn't hurt an eye. But at the same time, it's not something impressive, not eye catching.

Installing 3rd party stuff
It's very simple to invoke any system command from WIX. If system command is not enough, then a DLL or VB script can be called as well. Unfortunately it get's more complicated starting with Windows Vista and Windows 7. They have UAC (User Account Control) which denies pretty much all activity that was not explicitly accepted by user - e.g. blocks write access in some areas, disallows some programs. This is not really WIX issue, but being closely coupled to underlying MSI technology, WIX exposes some difficulties that we usually don't want to see or understand. So, any custom action (e.g. custom command invocation), that requires UAC signoff (or "privileges elevation") must be ran deferred. So in fact, it will be ran separately after the installer. Unfortunately deferred command does not see any properties or variables set during install process. So for example, if you want to remove extra files on uninstall, you need to think about communication mechanism, that will tell remove command the location to be removed and then run remove command deferred. That's much more than "rm -rf $DIR". The advantage is that you decide what privileges are used for which step (it's not so obvious with other 'advanced' tools).

Installing files
When installing the files, MSI maintains extra bookkeeping for rollback support. Unfortunately this is quite time consuming. In our case, whole application was 500M which meant extra precious minutes of installation time (and first impression) only for ability to click "Cancel"/"Repair". Disabling this bookkeeping is supported only in more recent MSI versions. This makes MSI technology look very bad when compared to any Archive/ZIP-based installers. The good side is, that latest MSI (e.g. included in Win7) is pretty fast, and it's only Windows XP where things are slow. During uninstall, naturally, only the installed files are removed. This is usually advantage, but if application generates any files, like cache, or stores files in many locations, then we want that removed as well. There's no out-of-the-box "remove dir" functionality.

MSI supports updates. Update can replace particular files in install. This time, our tool was managing updates by itself and there was no easy way to automatically map those updates to certain files. So we didn't use this functionality.

That's pretty much my first top five thoughts about WIX. At the end, it's also worth mentioning the community. WIX has extremely lively forum. Only rare questions pass without an answer. Unfortunately not many people make an effort to dig a bit into archives, so many basic questions get asked all the time.

I've got some other installer tooling to blog about as well. So for next entry, I need to decide whether to get deeper into WIX or give an overview of it's alternative. Don't hesitate to comment, if you'd like to hear anything in particular about WIX.