What Windows administrator doesn't recognize the letters "msi"? The Windows Installer service (the msiexec.exe program) and its .msi file package component are the de facto technology for Windows application setup. You're probably familiar with the primary benefits of using a Windows Installer application setup package. First, if a problem occurs during setup, the .msi package undoes the part of the installation it performed and rolls back—or restores—the computer to its previous state, thereby avoiding damage to the application or system. Additionally, an .msi-packaged application can repair itself when a user deletes a file from it. Finally, Windows Installer lets you use Group Policy to install software on users' systems. Although you probably know the basics of Windows Installer, a more in-depth knowledge of how Windows Installer and its .msi packages work "under the covers" can help you create custom application setup packages and better troubleshoot application setups. We'll start with a high-level review of the Windows Installer technology, then explore the structure of .msi packages and how they interact with the Windows Installer service.
Windows Installer Technology
Microsoft first shipped the Windows Installer technology about 4 years ago and subsequently made Windows Installer a core part of the Windows 2000 Server OS. Windows Installer 2.0 is included in Windows Server 2003 and Windows XP and includes support for Microsoft .NET assemblies (the unit of installation in .NET). Microsoft makes Windows Installer available in two ways: in the Windows OS as the Windows Installer service and as a software development kit (SDK). The Windows Installer service is the engine that installs Windows Installer packages (i.e., .msi files). The SDK contains specifications and APIs that govern the format and function of .msi files. You can download the Windows Installer SDK, which is part of the Platform SDK, at http://www.microsoft.com/msdownload/platformsdk/sdkupdate/sdkinfo.htm. Developers and vendors of application-packaging tools such as InstallShield Software, OnDemand Software, and Wise Solutions (now part of Altiris) use the SDK to create application setup packages. Developers often use application-packaging tools, which repackage old application setups into the Windows Installer format, to hide from users much of the complexity of the Windows Installer technology.
Products, Features, and Components
An .msi file is a complex database of application-installation instructions that contains dozens of tables, hundreds of columns, and sometimes other embedded files. The database contains information such as OS requirements for installing the application, steps to perform during the installation, and even the dialog boxes to present during setup.
An .msi file comprises a three-part hierarchy. The highest level is the product—the software application itself. A product has a unique product code that's represented as a globally unique identifier (GUID). At the next level are features within the product. Features are referenced by name and represent product functions that a user can choose to install. Figure 1 shows an example of features within an application setup—in this case, Microsoft Office Access and Microsoft Office Excel within a Microsoft Office setup. A feature is the unit of installation within a Windows Installer package. That is, when Windows Installer installs a package, Windows Installer installs (or uninstalls) features rather than individual files.
In Figure 1, you can see that Excel has many subfeatures, such as Help and Spreadsheet Templates. For each feature, the user can decide, at installation time, which subfeatures are installed locally on the user's computer or run from a server, which are "advertised" to be installed on the first use (signified by a 1 on the icon for a given subfeature), and which aren't installed at all. (For an explanation of advertisements, see the sidebar "The Power of Advertisements," page 62.)
Features consist of components—the third level of the .msi file hierarchy. A component is the basic unit of a Windows Installer package and is the building block of an application. A component can be a file or set of files, a registry setting, a shortcut, or a resource (e.g., icons). A key path is associated with the component. The key path designates the file or setting that must exist for the component to be fully installed. The key path is the basis of the self-repairing nature of Windows Installer-based packages. When Windows Installer repairs an .msi packaged application, the Windows Installer service checks all key paths of all components in the application for completeness. If a key path for a particular component is missing, the Windows Installer service traces the component to the feature it belongs to and reinstalls the feature. Thus, the time needed to repair an installed application depends in part on the number of components in the application package and the number of components that exist within the feature that contains the broken component.
The Windows Installer Database
As I mentioned earlier, an .msi file is a set of setup instructions organized as tables in a database. The Windows Installer SDK defines each table and column. You can use the Orca database editor tool in the Windows Installer SDK to view and edit the contents of an .msi file. The setup .msi file for Orca is in the \bin directory under the Platform SDK installation directory (e.g., c:\program files\platform sdk\bin). After you've installed Orca, you can open any .msi file. When you open a file in Orca, you'll see a list of the file's tables in the left pane of the Orca interface. When you highlight a table, you'll see its rows and columns in the right pane.
Figure 2 shows the LaunchCondition table in the Windows Installer package for Group Policy Management Console (GPMC). In the right pane, the table describes the minimum OS and platform requirements to install GPMC. The Condition column is a set of conditions that must be met during installation. The Description column describes the minimum requirements for the set of conditions. When Windows Installer begins to install the application, Windows Installer determines whether the launch conditions are met before proceeding with the rest of the installation.
Sequence tables are the heart of an .msi database and list the actions that Windows Installer must perform during an installation and the order in which it must perform them. For example, a sequence table tells the Installer engine to first check the launch conditions specified in the LaunchCondition table, then to copy the source files to the destination directory and make a set of registry entries. Sequence tables come in three types: Admin, Advertisement, and Install. The type of sequence table that Windows Installer uses depends on the type of installation it performs. Table 1 describes the three sequence table types.
Each sequence table type has two associated tables. One table—InstallUISequence—defines the UI dialog boxes that should be displayed in an interactive (i.e., user-driven) installation. The other table—the so-called "execute sequence" table (i.e., InstallExecuteSequence)—defines the steps necessary to perform the installation.
A sequence consists of a set of predefined standard actions that are included in Windows Installer and are listed in the InstallExecuteSequence table's Action column. The standard actions perform a variety of tasks—such as copying files, checking for newer versions of the software, and determining how much disk space is available for the installation. The SDK documentation and Orca give you a detailed look at what a particular Windows Installer package is up to. You can also use Orca to create custom actions that perform tasks that the standard actions in a Windows Installer package don't perform. A custom action might be a DLL that you write or even VBScript code that performs tasks such as checking Active Directory (AD) for certain values before continuing an installation.
The Property table is another important part of an .msi database. Properties are constants that you can define to control an installation's behavior. You can think of properties as environment variables for an .msi file. A frequently used property in Windows Installer packages is ALLUSERS, which tells the installation how application configuration information is stored—either per user or per machine. Property names are case sensitive, and you can provide them at the command line at installation time (as I explain later) or by using a transform (which I describe in the next section).
Transforms, Patches, and Merge Modules
When you obtain an .msi file from a vendor, chances are the .msi file won't do everything you need to deploy the package in your environment. For example, you might want to deploy the package silently using a software-distribution tool or install only certain features. Transforms are useful in such cases. A transform is a special type of .msi database file and usually has an .mst extension. Transforms apply to an application's setup at installation time. Essentially, they modify the default values in an .msi package to control the installation behavior as it occurs. The modified values aren't actually saved in the .msi file; they simply control what happens during a specific installation.
In contrast to transforms are patch files, or .msp files. Typically, a vendor issues a patch file when it wants to update a product but not issue a major release—security patches are good examples of a patch file. Installing a patch file permanently modifies the copy of the .msi file that's cached on the user's workstation. You should also apply any patch files to the application's source package to ensure that subsequent new users obtain the updated files.
Yet another variation of the .msi file is the merge module, or .msm file, a set of components that are frequently reused in application setups. For example, various third-party applications might use Microsoft Data Access Components (MDAC). Instead of reauthoring a setup for these shared components in every new .msi package, application packagers can reuse merge modules that the shared-component vendor provides. Merge modules are simplified .msi database files that contain only the features and components that application setups must share. Often, the actual component files are embedded in the .msm file itself, which lets application packages easily share merge modules. The .msm files are then merged into the main application Windows Installer package at package-authoring time.
When you author a new setup package, you can include the application files within the .msi file. Typically, files are included as embedded cabinet (.cab) files, which are compressed collections of files similar to .zip files. Including a .cab file in an .msi file is usually practical only if the .cab file isn't overly large. For example, Office has separate .msi and .cab files because the Office .cab files comprise several hundred megabytes. However, for smaller applications, including all required files for the application within the .msi file makes the file portable and easy to distribute to users. If you have an .msi file that includes an embedded .cab file, you can use the Windows Installer SDK's msidb.exe tool to extract the .cab file.
The Windows Installer Service
Windows Installer packages have a mutually dependent relationship with the Windows Installer service: Neither can exist without the other. Windows installs the Installer service by default on all post-Win2K versions of the OS; you can install a redistributable version—that is, a standalone version of the Installer service and related DLLs—on Windows NT Server 4.0 and Windows 9x. The Installer service runs in the context of the privileged LocalSystem user account. To start the Windows Installer service, you double-click an .msi file (e.g., in Windows Explorer); starting the service spawns a new Installer process (msiexec.exe) under the context of your user credentials. After Windows Installer has finished installing an application, the Installer service shuts down until the next time you use it.
The Windows Installer service provides a set of functions that are handy for deploying software, especially when you use them with the Software Installation feature in Group Policy. Chief among these functions is privilege escalation. When a typical nonadministrative, nonpower user tries to install an application on his or her computer by double-clicking an .msi file, the user's default privileges probably won't be sufficient to complete the installation. However, when you deploy the application through Group Policy's Software Installation feature, the Windows Installer service executes the installation using its LocalSystem security context.
More specifically, the Installer service spawns a new msiexec.exe process under the user's security context to handle the portion of the installation that's installed to the user's profile. The Installer service uses its own elevated security context (i.e., the LocalSystem account) to process the part of the machine-specific installation to which the user doesn't have rights. Applications deployed in this way are called managed applications. The privilege escalation that Windows Installer uses for managed applications is generally available only in Group Policy-based deployments, although you can also enable it outside of Group Policy Object (GPO)-based deployment through an Administrative Template policy.
The mutually dependent relationship between Group Policy and the Windows Installer service also includes the ability to perform advertisements. When you assign an application to a user in Group Policy, you in effect perform an advertised installation, as I mentioned earlier. Thus, the Windows Installer engine doesn't process an .msi file per se but rather an application advertisement script (.aas file). The .aas file is created when you use Group Policy to deploy the application. To create the .aas file, Group Policy Editor (GPE) actually calls a function exported by msi.dll (a core DLL that msiexec.exe uses) that generates a unique advertisement script within the GPO. Thus, when the Windows Installer engine processes the advertisement script, it knows where the associated .msi file is and what portions of the application to advertise. In other words, GPO-based software installation is tightly tied to the Windows Installer service, and vice versa.
Storing Installer Files on a Workstation
Let's look at what happens on a workstation when the Windows Installer service installs an .msi package. First, to facilitate rollback of a failed installation, Installer backs up any files it replaces to a temporary location on the user's hard disk—usually C:\config.msi. If you visit that folder while an installation is in progress, you'll see some oddly named temporary files that the Installer service creates. The Installer service deletes the temporary files after the installation is complete.
After finishing an installation, Windows Installer stores a copy of the installation's associated .msi file and any transforms that Windows Installer used to install the application in \%windir%\installer, assigning the files unique code names (e.g., 19fe9b79.msi). The files in \%windir%\installer are essentially cached copies of all the .msi files that Windows Installer has installed on the computer. Having the cached versions available lets a user change or remove an application without accessing the original installation source package, which might be on a server share that a roaming user can't access. Windows keeps track of all installed .msi-based applications; the installed features, components, and patches; and the file name of the cached .msi file (among other things) in the registry.
To determine which cryptically named .msi file corresponds to an application on your workstation, go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData. The keys under this location are organized by username SID, with the LocalSystem account, S-1-5-18, shown first and typically listing all applications that have been installed per machine. Per-user installations are listed under the corresponding user's SID.
Launching Installer Files at the Command Line and in Scripts
Two additional ways to launch Windows Installer packaged installations are from the command line or in a script. At the command line, you can execute msiexec.exe to perform various installation tasks. (You can find the complete list of command-line options for msiexec.exe in the Microsoft article "Command-Line Switches for the Microsoft Windows Installer Tool," at http://support.microsoft.com/?kbid=227091.) For example, you can use the command-line method to install one feature in an application package, such as the DNS console tools in the Windows 2003 Administration Tools (adminpak.msi). Use Orca to find the correct feature name—in this case, FeDNSConsole—then, at the command line execute msiexec.exe to perform the installation, as follows:
msiexec /I adminpak.msi ADDLOCAL=FeDNSConsole
This command uses the ADDLOCAL property to tell the Windows Installer service which of the package's features the service should install. The command-line method is a faster alternative to users choosing which features to install or to administrators using a transform file to install certain features.
The Windows Installer SDK includes examples of how you can use Windows Script Host (WSH) scripts to interact with Windows Installer and .msi packages. The WindowsInstaller.Installer object provides methods and properties that you can use in scripts to perform actions such as listing all .msi-based packages installed on a system, adding a .cab file to an .msi database, applying a transform to an installation, and comparing two .msi database files. For more information about Windows Installer scripting objects, see the sample scripts in the Installer SDK directory in the folder Samples\sysmgmt\msi\Scripts or at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/using_the_automation_interface.asp.
Go Forth and Install
As you've seen, Windows Installer means much more than just clicking an .msi file. The powerful Windows Installer technology lets you install applications in a robust and resilient way, but to get the most from it, you must understand how it works. Use the information in this article to explore Windows Installer and optimize your application-packaging solutions.