by David Cole, Senior Software Engineer, IBM
Install developers often need to include other products within their own setup. Flexera Software’s InstallShield 2009, coupled with Microsoft’s Windows Installer (MSI) 4.5, offers new options for chaining installs together while avoiding the problems associated with the existing options of merge modules and nested installs.
This white paper describes using chained .msi packages in InstallShield 2009 and MSI 4.5 to componentize a setup. You will learn how to include other .msi packages within your own so that the result may be installed with the appearance of being a single product. The white paper also compares chained .msi packages with InstallShield prerequisites, which provide another method for including third-party setups.
Footnotes are added with links to the InstallShield and MSI help for additional details.
The problem with merge modules
Microsoft originally developed merge modules as the preferred method within MSI for developing components to be shared among multiple products. A key problem with merge modules, however, is that the contents of a merge module are installed under the ProductCode1 of the product that includes the merge module. Consequently, merge modules cannot be serviced independently; any service update for the merge module must be packaged as a service update to the containing product.
For example, suppose a version of Acme WidgetWorks included Microsoft’s Windows Scripting Host 1.0 merge module, and that Microsoft later released a service update for that merge module. Acme WidgetWorks would then have to release a service update of its own that includes the Microsoft update. This can quickly become a service nightmare, especially if there are urgent security issues involved.
The problem with nested installs
MSI has always had the restriction that only one MSI install can make system changes at a time. This locking mechanism helps ensure system integrity, but also limits where and how nested installations (sometimes called concurrent installations) can be run. Microsoft acknowledged the need for one setup to be launched from within another and developed special custom action types for nested installations2. Microsoft has since deprecated these types of custom actions and discourages their use3, citing that, “…they are difficult for customers to service.”
A new hope: chained .msi packages
Chained .msi packages is a new feature of MSI 4.5 and is supported by InstallShield 2009. This function allows individual .msi packages to be integrated into a containing, parent .msi setup so that the combined install is managed as a single transaction. Thus, if the install of one .msi package fails, then the entire install is rolled back. When the parent product is uninstalled, the chained .msi packages are also uninstalled (although there are other options available).
Perhaps most importantly, each constituent .msi package is installed under its own ProductCode. This means that each product can be serviced independently and thus avoids one of the major problems with merge modules.
MSI 4.5 uses the chained .msi package’s own ProductCode to determine whether that package has already been installed or not, and thus skips the install step for packages that have already been installed. Similarly, if a chained .msi package has been upgraded so that it now has a different ProductCode, or if the package has already been uninstalled, then the uninstall step for that package is skipped in the parent uninstall. Thus, chained .msi packages behave as you would generally desire without having to write additional code.
Considerations for chained .msi packages
Before you include chained .msi packages in your installation program, you should consider the following:
Including MSI 4.5
Chained .msi packages require the use of MSI 4.5, which is included with InstallShield 2009. (The GA version of MSI 4.5 became available with InstallShield 2009 service pack 1.) Unlike earlier versions of MSI, MSI 4.5 is added as an InstallShield Prerequisite4. We’ll discuss prerequisites in greater detail later in this white paper.
MSI 4.5 is only required for the parent .msi package. Child packages are not required to use any particular version of MSI.
Installing MSI 4.5 does require a reboot, although the symptoms vary based on the version of Windows being used. On Windows XP and Windows Server 2003, the reboot is automatically deferred to the end of the setup. That is, on these versions of Windows a setup that installs MSI 4.5 will run to completion and the user will be prompted for a reboot when the setup completes. On Windows Vista, a reboot is required immediately after MSI 4.5 is installed. Based on discussions in the InstallShield 2009 Community5, the cleanest approach on Vista is to force the reboot by:
- In the Redistributables view, right-click on ‘Windows Installer 4.5 for XP SP2 and later (x86)’ and select Edit Prerequisite.
- In the resulting Prerequisites panel, select the Behavior tab and edit the ‘If the prerequisite appears to need a reboot’ drop-down list and choose ‘Prompt the user to reboot the machine even if nothing is detected, and resume on reboot’, as shown below.
On Windows Vista, you can defer the reboot by pre-installing MSI 4.5 and then launching your setup. While perhaps not elegant, this two-step approach can be a valuable alternative for system administrators.
Organization of install media
Chained .msi packages can either be streamed into the parent .msi package or accessed from a specified location, usually on the install media. Streaming chained .msi packages is generally preferable, but you should consider the following:
- The overall size of a .msi file is limited to 2GB, so the cumulative size of the parent setup must not exceed this limit.
- Streamed packages are not visible to the end user, and thus cannot be accessed and installed independently.
- Streamed packages must be streamed out into temporary storage during install, and thus affects both performance and temporary disk space requirements.
- A repair operation for a chained .msi package may prompt for the install source location, and that can be more easily located if the package is on the install media (i.e., not streamed).
- If some chained .msi packages are optional – for example, they’re associated with features – then not streaming the chained .msi packages allows the end user to remove any packages that are unneeded, and thus reduce the size of the overall install package. Administrators appreciate being able to reduce an install image to only that which is needed for their environment.
If you choose to locate the chained .msi packages on the install media then you should consider a directory structure for storing the .msi packages. In the event that the packages could have accompanying files with non-unique names (such as language transforms), it’s best to create a separate folder for each package, perhaps similar to:
It’s helpful to be aware of the Postbuild tab6 on the release settings, which allows you to copy an installer to a specified location as part of the build. Set the ‘Distribute after build’ property to Yes to copy the build output to a staging area automatically after each build.
You can also use the Support Files view7 in InstallShield to incorporate the chained .msi packages as part of the overall InstallShield build. To do so, you’ll want to use the Disk1 item under Advanced Files so you can add a folder for each package. This approach works well for a non-compressed build, such as what you’d create for CD-ROM distribution. Disk1 files are not included in a compressed setup.exe, however, so this approach does not work well when you need a single self-extracting executable.
Organization of MSI 4.5 redistributables
Ah, the good old days when there were just two MSI redistributables, one for Windows 9x and one for Windows NT/2000, and either could fit on a floppy diskette. With MSI 4.5, there are now seven different redistributables, given the different 32- and 64-bit versions of Windows and the different underlying chip sets. If you include all seven versions, then your setup will grow by a whopping 43.2 megabytes.