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.
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
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
- Rollback to the original system state if the installation fails for any
- 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
- 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,
- Check for preconditions (for example, the presence of Internet Explorer or
- 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