Channels ▼
RSS

Creating a Better Installer


February 2002/Creating a Better Installer

Most developers breathe a sigh of relief when the coding and testing is complete, but you’re not out of the woods until you can get the application successfully and safely installed on your client’s computers. Aside from playing games on your computer, the most adrenaline-inducing moments are probably whenever something is being installed. In many cases, people just plain expect that the installation will break something. An installation frequently requires running with Administrator privileges, so it needs to behave responsibly. I’ll outline the areas where installation design seems to cause the most difficulty. Following these guidelines when designing an installation should help reduce the adrenaline levels of your customers.

Choose the Right DLLs

The number one reason why people don’t trust installs is because they expect the installation to change a system DLL and break other applications. This is the situation usually referred to as “DLL Hell”. We’ll talk about Windows File Protection later, but the good news is that Microsoft packages many of the redistributable DLLs into installation setups, so it’s relatively rare to have to pick and choose the individual DLLs to ship. Some of the common packages are listed in Table 1.

When you run these packages, they install the appropriate DLLs to support the application. If you search the Microsoft web site for these package names, you’ll find details about the DLLs that they install. The file Redist.txt in the Platform SDK also has a list of packages that must be used to install support for features like the Common Controls and Component Categories. On the other hand, the file Redist.txt that comes with Visual Studio 6.0 can get you into a lot of trouble if you’re not careful. For example, it lists RPCRT4.DLL as “Redistributable Code - Standard”, and when you run your favorite dependency walker, and it says RPCRT4.DLL is a dependency, you can be forgiven for thinking you need to install it on your client’s systems. However, this DLL has been a standard part of the operating system since almost the very beginning of Windows 9x, and installing it on a client system will probably break it. My guess is that these lists of redistributable files date from the time that Windows 95 was first released, with none of the functionality that was added later (such as COM). Incidentally, if your application has to run on very early versions of Windows 95, DCOM95.EXE is the package that installs RPCRT4.DLL and other COM DLLs.

You also have to be wary of the DLL that supports code written using Visual C++ ATL. ATL.DLL has an ANSI version for 9x and a Unicode version for NT, both with the same name.

Newer Windows operating systems have Windows File Protection. This is designed to prevent installation programs from replacing the approximately 2700 (on Windows 2000) critical system DLLs, OCXs, and drivers that keep the system reliable. Occasionally, there are attempts by people to circumvent this protection, typically because their application doesn’t work with the version that Windows insists on keeping on the system. If they could only get the “right” version on the system, their application would work. The harsh reality is that the application is broken if it doesn’t work with the system DLLs on a system with File Protection.

You can get a list of the protected files by compiling and running the program in Example 1. You’ll need to link to SFC.LIB in your project settings. I should also mention that Microsoft implemented a scheme called “side-by-side” components that is intended to reduce the conflicts that occur when many applications use the same DLLs. Also, keep in mind that redistributable files are very different with .Net applications. We’ll discuss this later.

Keep Up with New Redistributables

Once an application installs properly and works correctly, it’s just the beginning. Microsoft will ship service packs to the operating system and supply new redistributables from Visual Studio service packs. New versions of MDAC, Internet Explorer, SQL Server, and other products will be installed on client systems and update the DLLs. Even though you might not need to install any new redistributables for your application, you still have to test that your application still works with them. You can’t stop other products and other installations putting new versions of Microsoft software on the system, so you have to make sure your application works with them.

Personal Settings

One of the other reasons that people worry about installations is that an installation might change your personal settings without even asking your permission. Setups shouldn’t change Active Desktop settings, wallpaper, screen savers, and so on. These settings belong to your customer, not you, and if you really need to change them (and I doubt that you really do), always ask permission. The same kind of situation can happen with the applications that handle file extensions. You may have noticed, for example, that applications that handle HTML files and varieties of multimedia files may assume that just because you’re installing the software, you want it to become the default handler for all of those file extensions. If an installation notices that there are already handlers for a particular file extension, it’s a good idea to let the client know that the application being installed is about to become the default handler for the files and give them a choice to change it.

Don’t Insist on a Particular Software Set Up

Let’s say that Bob and Alice are developing programs for an application. One day Alice goes to Bob and says “Look, Bob, my program requires Windows Service Pack 1, but your program always runs before mine, so I want you to test for the service pack so that I don’t have to.” Bob would point out that it’s Alice’s responsibility, not his. However, you’ll often find this situation when the first program is the installation program. But is it a good idea for an installation program to do these kinds of checks? Given that service packs can be uninstalled, a one-time check when the application gets installed seems pointless. You’ll also find a lot of advice saying that service packs should be reapplied after every installation. There are people who don’t trust installations, and they’ll re-apply service packs after an installation whether they believe that Windows File Protection will save them or not. These customers will simply be annoyed that the installation effectively forced them to apply the service pack twice. There’s also the question of what the application does if the service pack is uninstalled. It makes no sense for an application to fail because the customer had to uninstall a service pack, so the right answer here is that the application should check for its requirements and issue messages any time they’re not met.

Although this example mentions service packs, it applies to similar situations such as required versions of Internet Explorer.

There are many other similar situations that are often intended to help the customer but which can have unintended consequences. You might see situations where an install will abort if it can’t ping another computer or if some piece of hardware isn’t installed. These all tend to be variations on the same theme: the installation is doing checks intended to protect the application when it runs. Think about these situations and perform the checking in the application wherever possible to make the installation process simple, reliable, and capable of being performed whenever it is convenient for the customer.

Installing Other Setups

It’s not unusual to find installations that also install other applications or supporting software by firing off a separate setup program. There are situations where this is not the right thing to do, however much it might seem to be a help to your clients. For example, sometimes you’ll find that you need to install a version of MDAC (Microsoft Data Access Components), or provide support for MMC by running Microsoft’s self-extracting immc.exe program. If you run these in silent mode, you may find that they require a version of Internet Explorer that isn’t on the client system, so their installation will fail. In other cases, they may require a reboot, so your installation program finds itself having to deal with a reboot that it didn’t expect. In addition, let’s say your application might be installed in other countries. You should not install an English MDAC onto a non-English system. There are many cases (including MMC) where there are localized versions of shared software (Adobe’s Acrobat Reader is another example) and you should not install the English version. As in the physician’s Hippocratic oath, the first rule of an installation is “Do No Harm,” so when in doubt, don’t install it. What is better for the client? That your application doesn’t work, or that you install the wrong files and all the applications on the client machine stop working properly? Remember, the client can always be given download instructions to get the appropriate localized versions.

Configuration and Data Collection

Sometimes installations ask for data, or to set up some configuration options at installation time, and many users find it daunting. It’s not obvious whether they’ll ever get a chance to look at it again in case they make a mistake and have to correct it. From the user’s perspective, if the installation asks you to enter a username or an IP address, you’re probably wondering what will happen when the username expires and you want to change it, or that IP address needs changing. Remember, this may be the first time the client has been anywhere near your application and may not have any idea how they can change these things later. The best answer to these issues is to perform the configuration steps in the application, not the installation. The application should have a configuration utility that can be used to alter the configuration settings any time the client wants to change them, not just during installation. In many cases, you can arrange for the configuration utility to be the first thing the user has to run.

There’s another reason not to offer special configuration dialogs during an installation — the installation may have command line choices to suppress the user interface. In this case, your client might want to silence or automate the installation because it’s being deployed to many systems, and configuration dialogs during an installation defeat the client’s wishes.

In other cases, you could find that your application might be shipped pre-installed onto a system and there will be no installation process that your clients will ever see — they’ll go straight to the Start menu and use it — they’ll never be able to configure during an installation. While most systems still require a separate installation process, it’s possible that systems may be shipped straight to the client with software all set up and ready to go, and your application might be installed by a client on some systems but not on others, as the marketing folks decide. Windows CE, server appliances, PDAs, and XP Embedded are situations where there may never be an installation process that the client will see.

Sometimes an installation is expected to do a surprising amount of work for the application being installed. For example, the installation might be asked to create databases. But this raises issues about how much of this database generation and population process can be reversed if the installation fails elsewhere. If the user retries the installation later, how much code do you need in the installation to deal with files or duplicate database entries left behind by the failed prior installation? In addition, what if creating a database requires something like SQL Server to be present on the client system and your client hasn’t installed it yet? You could require that SQL Server be installed first, but then you’re back to insisting that the client perform installations in a specific order. Presumably it’s possible for several different installations to require an installation sequence where one of them simply cannot be installed because its sequence is incompatible with the sequence required by the others, and if you’ve ever experienced this situation, I’d like to know the details.

It’s surprising what installations are sometimes expected to do, so try to resist complexity and be aware of situations when you’re writing code that more properly belongs in the application itself. Once the installation goes beyond the usual framework of copying and installing files, services, shortcuts, registry entries and so on, it’s often a recipe for a difficult installation process.

License Agreements and Readme Files

In some ways, a License Agreement is a type of data collection because the user might have to accept it before the installation will proceed. This has the same potential issues that we discussed earlier about configuration and user dialogs during an installation, so think about showing the License Agreement outside the installation process. You may have noticed, for example, that recent versions of Adobe’s Acrobat Reader no longer show the agreement during the installation — it’s now shown when you first view an Acrobat PDF document.

Installations often give an option to print the Readme files that contain late-breaking information, but an inexperienced user will have no idea whether the information will ever be available again. For a CD-based installer, the most useful place for this kind of information is as part of the Autorun that is displayed when the client plays the CD. Alternatively, really late-breaking information might need to be on a web site, so perhaps you can install a URL to your support web site. Again, remember that there might be a day when your application is shipped pre-installed on a system, so a license agreement or Readme shown at installation time will be no help.

Don’t Compensate for the Application Design

It’s not unusual for an application to be designed so that it won’t work properly unless the installation can modify the system in a certain way. For example, the installation might be asked to make a certain set of registry entries for every user on the system. This can be rather a complicated task to perform during an installation. This could turn out to be the result of the application expecting to find some registry entries in HKEY_CURRENT_USER whenever a user logs on. It also is a potential design flaw in that it doesn’t allow for a new user who might log on the machine, and therefore who doesn’t have a HKEY_CURRENT_USER entry. The correct application design for this situation could be to install the initial default set of registry entries in a HKEY_LOCAL_MACHINE key. Then, when the application first runs for a particular user, it can use these entries to seed the HKEY_CURRENT_USER entries, and from then on allow each separate user to keep their state in HKEY_CURRENT_USER.

Let’s also look at a case involving program control. An installation developer was asked to install a program shortcut in the Startup program group. This worked fine except that it wasn’t really what was required. The Startup group is run only when a user logs on, but the real requirement was to run the program when the system starts up. The next alternative was to put entries in the Windows NT registry in the HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run key. However, this too runs when a user logs on, and not when the system reboots. There was another interesting twist — the program didn’t have a user interface, and it ran continuously, so when it became time to install a new version on an NT system, the installation required a reboot because the executables were in use. The point of this story is that installation issues have to be included in the application design. In this particular case, this is the kind of application that should have been implemented as an NT service, because that satisfies the requirement to run the application when the machine starts up, and because installation programs can use APIs or Installer technology to safely start and stop services.

Anyone who’s spent time on installations will understand that it can be difficult to go and tell the designer that the application needs changing because of these kinds of issues, but it’s increasingly the case that application design and behavior needs to take the installation into account.

Reboots

Of course you should never reboot a system during an installation unless you absolutely have to. This is one of the times where it really helps if you know your customer. We’ve all got PCs at home and at work, and maybe rebooting a PC is no big deal. However, companies such as Unisys and others are shipping 32 processor systems with thousands of people connected to them, and using the PC installation model in this world is a bad idea. The customers of larger systems want mainframe-class reliability, and they don’t want to disrupt their users because of an installation. Often reboots can be avoided with a little extra work, and if you have a Windows Installer installation on Windows 2000, it will try to detect in-use files and prompt you to shut down the applications that are using them.

I encountered a situation where an installation program was asked to perform a reboot after creating service entries in the registry. In this case, the developer was unaware that installation programs can install, start, and stop services. There was a mistaken assumption that a reboot was necessary to start a service installed as Automatic initiation (start up after a reboot), but in fact, the installation could simply start it.

Use the Windows Installer

Microsoft’s new Installer service has a steep learning curve, and its framework imposes some restrictions on how installations work. It is nothing like older installation technology, and you’ll have to learn at least two large new areas: First, the Installer technology itself, the database structure, the tables, properties, sequences, and the rules for upgrades and reinstallation. Second, there’s the tool you use for building the Installer database, whether it’s something relatively basic such as Microsoft Visual Studio Installer or a more fully featured product from companies such as InstallShield or Wise.

In the Windows Installer world, these are some of the main issues you’ll have to be aware of:

  1. The Installer is a framework with fewer opportunities for radical alteration of client systems than older setups. Yes, you can write code and insert it at various places in the installation sequence, but you’ll find it harder to perform complex tasks during an installation. If you have a complicated installation setup, use the opportunity to redesign it to fit into the Windows Installer framework. As with any programming or development framework, you’ll find it safer to follow where the framework wants to take you rather than bend the framework to fit an awkward design.
  2. A Windows Installer setup will do things such as roll back the entire installation if part of it fails. There are self-repair features that will restore missing files and registry entries. The payoff for the end user will be a more reliable installation as long as the developer of the installation follows Installer recommendations.
  3. An Installer setup can reduce the difficulties of installing both 32-bit and 64-bit applications. For example, registry entries in an Installer database are fairly agnostic — they are not specifically for a 64-bit program or a 32-bit program. The differences between an installer database for the 32-bit and 64-bit versions of an application are probably fewer than you might imagine, particularly relating to registry entries and COM registration data. In Windows Installer terms, COM registration and other registry entries often just require you to mark the component as being a 64-bit component and the right things will happen.
  4. Installer technology will be better at differentiating between the “install for all users” and “install for the current user” cases than programs writing their own registry entries. This will get more important as NT-based Windows (NT, Windows 2000, XP) become more popular in the consumer market. The idea of a shared computer in a family environment and XP’s “Fast User Switching” are about family systems where each user has their own view of the system, and installing for the current user is what makes this work. Of course, the application also has to follow the rules about keeping data in user-based locations instead of system-based.
  5. Installer technology is better at side-by-side component sharing than traditional installation tools. For example, a typical in-process server will self-register by writing the entire installation path to the InProcServer32 key, whereas the Installer will write only the file name if you’ve built the Class table right. There’ll be a lot more you’ll need to do (see the MSDN documentation on side-by-side sharing) but you won’t need to worry about all that DLLRegisterServer code writing absolute paths.
  6. Merge Modules could be described as the Installer equivalent of COM objects. They contain files and functionality that you can plug into a host installation setup. Visual Studio 6.0 SP5 shipped with about 40 Merge Modules for the DLLs and OCXs that are required to support programs developed with Visual Studio. They are becoming a standard way to redistribute functionality for installation.
  7. Windows Installer version 2.0 has explicit support for installation of application assemblies built by the .Net technology. There are tables to install assemblies and standard actions to publish them either as private or shared. (Side-by-side assemblies are available on XP.) As of Beta 2 of the .Net Framework, there is one Merge Module that contains all the .Net support. Not only does this include the mscor*.dll files, but also the compilers that are required to perform run-time compilation of C#, VB, and IL. The use of .Net COM Interop requires extra installation work because exposing legacy COM servers to .Net (and .Net servers to legacy COM clients) requires generation and installation of wrapper classes and registry information. For example, your current COM clients expect COM registration data in the registry. Installing a .Net server for use by legacy COM clients therefore requires installation of the registration information that the .Net tool REGASM.EXE creates.

Test the Product as Installed with the Installation Setup

This might be an obvious thing to do, but the differences between an application that works on a developer’s system and an application installed on a client machine are sometimes overlooked. There are a number of reasons why testing must be done with the installation program:

First, developer’s machines typically contain every DLL in the Microsoft universe, so any DLLs required by your application are virtually certain to be there on your development system. This is not the case on your client’s systems. The ideal test is to install on a system with the bare bones of the Windows OS on it, and then test your application, looking for missing DLLs that your application needs in order to work. It’s also not unusual for an application to work fine on Windows 2000 but fail on Windows 9x, and it’s often just a matter of identifying which supporting DLLs you need that aren’t installed with the operating system.

Second, when application installations are built to use the Windows Installer service, it’s very common (and a Microsoft recommended practice) to have the COM class information stored in the database tables in the MSI file. The application developer probably built the application on a system that automatically self-registered COM servers (typical in a Visual Studio environment), but this is not how the Installer will create the registry entries on your client’s system. Your COM server’s self-registration code will not be run on the target system if the Windows Installer is applying registration entries from its Class table.

And last, perhaps you’re used to installing services by running them with a -Service command line, and although you could still do this it’s not recommended. Installer technology has specific support for installing and configuring services, and controlling other services that you might wish to start or stop. It will automatically start and stop dependent services as long as you configure the service information dependencies in the Installer database. As you can see, the development environment probably tests a service after it’s been installed with a -Service command line, but services installed from the Installer database are not installed this way, hence the need for testing the Installer setup.

Beware of Data File Updates

Sometimes an installation will install data files that are intended for use by the customer. Perhaps an Access database file is installed with the intent that it will be updated, or template files are installed, and the user updates them. However an installation program, by default, will uninstall what it installed in the first place, so files like these will be removed on an uninstall, which will surprise your customers if they expected to keep them.

There are also issues in the area of updating data files. It can be surprisingly difficult to get a data file updated during an installation if the customer has modified it and therefore changed the modify date to be later than the version you’re attempting to install on top of it.

Datacenter and Drivers

Microsoft’s Windows Datacenter operating system is the host OS for certified configurations of hardware and kernel drivers, known as Datacenter Certification. The Datacenter configurations are tested, and customers running a certified configuration have certain support guarantees. Installing a non-certified driver can void these support guarantees. Tools are supplied that customers can run to check that their configuration is still certified. To state the obvious, drivers are kernel code and can crash the system. If your application uses drivers and you expect to be installed on Datacenter, it’s a good idea to first get your driver certified, signed and driver tested. You should also expect Microsoft’s requirements for driver certification to get more stringent in the future, including passing driver tests and getting digital signatures.

Remember Security

Installations are typically given the freedom to do almost anything to a system. Many of them require Administrator privilege to work on NT/Windows 2000. However, what you should aim for is an installation that requires Administrator privileges only if you’re installing for all users on the system. If you’re installing for the current user, you should plan to install without Administrator privilege because you don’t need to alter things like NT/2000 services (which are system-wide anyway) or update folders and registry areas that are restricted to Administrators. There is likely to be a customer expectation on shared systems that non-Administrators can install applications for themselves, without calling corporate help-desks, or without calling Dad if Junior is installing a video game (or vice versa).

First Impressions Last

The installation may be the first time your customers will experience your company and your product, and their experience with it may well determine whether they come back to you again. These guidelines are intended to help you make the design decisions in your application installation that will make it robust and reliable.

Resources

The Windows Installer SDK is part of the Platform SDK — you’ll find documentation and sample code in VBScript and C++.

http://www.installsite.org — An excellent resource for keeping up with installation technology, tips, and tools.


Phil Wilson is a software engineer Unisys Corporation, working with integrating Windows Installer technology into development projects. He has a BSc in Chemistry from the University of Aston in the UK. You can reach him at phil.wilson@unisys.com.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.