6.1 Windows Installer

Visual Studio .NET relies on Windows Installer for the underlying installation technologya Setup project simply produces a Windows Installer file. Windows Installer provides a standard way of dealing with the installation issues that most applications encounter, such as dependency management, uninstallation, and system configuration. Windows Installer has been built into Windows since Windows 2000 and Windows Me, but it can also be retrofitted to older versions of the OS back as far as Windows NT 4.0 and Windows 95.

When you build a Setup project, Visual Studio .NET creates an installer file containing all of the components required for the application to run, and any installation details such as registry settings. When this file is run, a standard Windows Installer user interface such as the one shown in Figure 6-1 will appear.

Figure 6-1. A typical Windows Installer

You do not usually need to write any code for a Setup project. Windows Installer uses a declarative approachit examines the contents of the installer file and works out what steps are required to complete the installation. For example, Windows Installer detects whether any of the required components have already been installed (which would often be the case for any libraries that your application depends on) and makes sure it copies only the files it needs to. Windows Installer deals with issues such as component version conflict resolution for you. You may, of course, add bits of code (called custom actions) when the built-in installer facilities do not meet all of your requirements, but for many projects, you will be able to create an installer without writing any code at all.

As well as providing a basic user interface and installing files, a Windows Installer file can configure the registry, create and configure IIS applications, and register new file types with the system. You can always write installation code if you have special nonstandard installation steps to perform, but for many applications, you will never need to do this.

Visual Studio .NET Setup projects provide a level of abstraction above the Windows Installer technology. This is useful because it simplifies the creation of installers quite considerably. However, it does mean that there are certain restrictions on how what can be achieved. (For example, your installer's user interface can use only the templates supplied by Visual Studio .NETyou cannot design your own.) If you have to build a particularly complex installer, you may need to consider using either the Windows Installer SDK or third-party installer builders, such as InstallShield or Wise.

There are two kinds of Windows Installer files. The type you choose to create will depend on whether you have written an application or a component that will be used in another application. Applications are represented with .msi files, or as they are sometimes somewhat confusingly called, Windows installers. Components are represented with .msm files, also known as merge modules.

6.1.1 Merge Modules

Merge modules represent a body of code likely to be used by more than one application. They are the reusable black boxes of the installer world. Merge modules are never installed in isolationthey are installed as a result of being contained inside the .msi file of an application that needs the component.

If you have created a shared component such as an ActiveX control, a Windows Forms Control, or a .NET class library, this would be an ideal candidate for a merge module. Such components are made to be reused and would usually be installed only as a result of installing an application that uses them. You should create a merge module for any such component. This will make it simple for whomever writes the installer for an application that uses your code to ensure that your component is installed correctlyhe will just include the merge module in his installer.

Merge modules vary in size and complexity. Some contain just a single DLL. For example, Microsoft provides a merge module for GDI+, which installs only the single redistributable GDIPLUS.DLL file. Others can contain tens or hundreds of filesfor example, dotnetfxredist_x86_enu.msm contains more than 200 files.

The main purpose that merge modules serve is to make sure that shared components are installed correctly. Without merge modules, application .msi files could just contain all of the files that make up the components they are using. (For example, an application might copy GDIPLUS.DLL directly into the Windows system directory as part of its installation procedure.) However, if the components in question have installation requirements of their own, such as registry configuration or custom installation steps, it becomes harder for an application installer to install the component correctly. But since a merge module can contain its own complete set of installation requirements, an application .msi can simply contain a copy of the merge module and rest assured that Windows Installer will perform all of the necessary steps.

Also, because all merge modules have unique identifiers, Windows Installer is able to recognize when an application depends on a component that has already been installed. This allows it to avoid trying to install components that are already present. Furthermore, it allows Windows to maintain an accurate list of which components are being used by which applications. This prevents the uninstallation of an application from removing shared components that are still in use. It also makes it possible for an application to be repairedif a file required by a program has been deleted (e.g., the user inadvertently removed a directory), Windows Installer can detect that the necessary files are missing and put them back.

This technology also makes it much easier for component developers to make sure that consistent sets of files are installed. Without merge modules, an application could easily ship a subset of the files that constitute a component. And this could easily result in a machine having a mixture of files from multiple different versions of the component, which would be likely to cause problems. But if components are always installed as merge modules, this cannot happen, since the suite will always be installed as a single unit.

Windows XP introduced the capability of having multiple versions of a shared component installed simultaneously. This is known as side-by-side installation. For this to work, it is particularly important for the OS to know which DLLs belong to which versions and which applications are using which versions. The use of merge modules makes it easier for Windows to detect this.

So if you are using a shared component, always include its corresponding merge module in your Setup project. If you are writing a shared component, you should create a merge module for that component. You choose between creating an application installer (.msi) and a merge module (.msm) by selecting the appropriate Setup project type.