Basics of the Windows Installer Service
If you're a Windows user, you've used the Windows Installer Service. First introduced with Office 2000, the Windows Installer Service is the standard method for installing (and uninstalling) software for all current versions of the Windows operating system. When you see a dialog box like the one shown in Figure 1, you're interacting with the Windows Installer Service.
Figure 1: A dialog box based on the Windows Installer Service
If you're developing your own software, you're probably interacting with the Windows Installer Service from the other direction: you'll be building a setup that uses the Windows Installer Service to do its work. There are a variety of tools to do this, from the free Orca editor that's distributed with the Windows Installer SDK, to Package and Deploy projects in Visual Studio .NET, to professional tools such as Wise for Windows Installer and InstallShield DevStudio.
Either way, you may have been treating the Windows Installer Service as a "black box", with only the vaguest of ideas as to how things work. To make the best possible use of the service, it's worth knowing the basics. That's where this article comes in. I can't teach you everything about the Windows Installer Service in this small space (that's what the Installer SDK is for), but I can provide a broad overview.
Packages, Components, and Features
Let's start with three of the most important concepts: packages, components, and features. An Installer package is all the pieces needed to install an application: the .msi file as well as external .cab files or standalone files that contain the actual bits to be installed (the software to be installed can also be stored in the .msi file itself). Apart from your own software, the most important part of the package is the installation database. This is a relational database that the Installer Service reads to tell it what to do when installing your software. Though there is an API for interacting with the database, you're unlikely to need this in most situations).
Within the database, you'll find components and features. The easiest way to think about these two things is that features split up your application from the end user's point of view, while components split up your application from a programming point of view. For example, spell-checking, help files, or templates might be features, while all of the files and registry keys necessary to install a scripting engine could be a component.
Features can be (and often are, in complex packages) hierarchical. Any parent feature can have one or more child features, and those child features can have their own child features. If a child feature is installed, the parent feature is automatically installed as well, but installing the parent doesn't require installing all of the child features. Features are unique to a particular package.
Components consist of files, registry keys, shortcuts, and other resources. Components are identified by component IDs, which are GUIDs. Components are not necessarily unique to a particular package; they're designed to be shared across multiple packages. That way, if one package installs a component (such as the VBA Editor), other packages won't reinstall it. The Windows Installer Service takes care of keeping track of how many installed products are using a particular component, and will not uninstall the component if any product is still using it.
Some authoring products will create precisely one feature for each component in a package (and vice versa), but that's not a requirement. As far as the Installer Service is concerned, a feature may require multiple components, and a component may be used by multiple features.
I've already touched on one of the benefits of using the Installer Service (tracking the usage of components) but there are plenty of others. Here are some of the benefits that any software using the Installer service gets "for free":
- Rollback to the original system state if the installation fails for any reason.
- Very clean uninstallations, which protect the system from breaking if the user uninstalls an application.
- The ability to quickly check the health of an installation, and reinstall damaged pieces. You can call the API to do this directly from your application, a benefit the Installer calls "resiliency."
- The ability to schedule or suppress reboots when installing software.
- "Installation-on-Demand" which lets you install software faster. This works by making a feature available to an application but not actually installin it until the user tries to use it.
- Advertisement of applications. This is installation-on-demand on a larger scale, placing the shortcuts for an application on a system but not setting up the software until it's used the first time.
- Support for several different ways of modifying packages, including transforms that can be applied by administrators to customize the way an application is installed and patches that let developers upgrade a package without completely replacing it.
- Merge modules, which are a way of putting a component (or several components) into a sort of mini-package that can be picked up and used as-is when you're authoring your own package. This makes it easy to drop shared components like the Microsoft Data Access Components (MDAC) into your setup.
- Administrative installations, which set up your product to a network share so that users can install it without a CD.
- A command-line interface with many options including several levels of logging, which can be very useful when things start going wrong.
Of course, you're not required to use all of these features in every package, and you need to exercise caution with some of them. Install-on-demand, for example, is responsible for the Windows Installer popups that afflict some users during routine use of Microsoft Office. Unless there's a good reason for install-on-demand, beware of it.
At the heart of the Windows Installer Service is the Installer Engine, which does the actual work of installing your software. It does this by reading the database inside of your product's package, which contains a list of actions. These actions can tell the Installer Engine to do a wide variety of things, including:
- Check for preconditions (for example, the presence of Internet Explorer or MDAC
- Search for previous versions of an application to upgrade
- Create folders
- Create shortcuts
- Install or delete files
- Install or remove registry keys
- Move or copy existing files to a new location
- Install, remove, start, or stop Windows services
- Install or uninstall Common Language Runtime (CLR) assemblies
- Install or remove ODBC drivers and data sources
- Register COM classes or COM+ applications
- Modify environment variables
If the built-in actions don't cover what you need to do, you can write a custom action. A custom action can execute VBScript or JScript code, run a command-line application, or call functions from an external DLL. With custom actions, you can extend the Installer Service to cover just about any imaginable software installation process.
For More Information
There is a lot more to learn about the Windows Installer Service if you get serious about tapping some of its more advanced features. For more information, try these resources:
- The Windows Installer SDK, a part of the Windows Platform SDK. This is the official documentation for the installer.
- InstallSite, an entire site of resources for setup developers.
- My own book VB/VBA Developer's Guide to the Windows Installer. The book is now out of print and only covers version 1 of the installer, but it's more accessible than the SDK and you can download a copy of the galley proofs for free from my website.
Start with these resources, and you may find that your can streamline your software setups and make them more enjoyable for your users. The learning curve can be steep but the benefits are substantial.
Mike Gunderloy is the author of over 20 books and numerous articles on development topics, and the lead developer for Larkware. Check out his MCAD 70-305, MCAD 70-306, and MCAD 70-310 Training Guides from Que Publishing. When he's not writing code, Mike putters in the garden on his farm in eastern Washington state.