Philip Hofstetter writes in his blog about things that setup authors do poorly. I don’t disagree with his observations, but I do disagree with his assertion that these problems stem from inadequacies in the MSI technology itself. Let’s take a look at his list of bad practices:
Use a .EXE-stub to install the MSI engine
I would agree that this is something that is typically no longer required, unless you’re using features in newer versions of the MSI runtime that are not present on the typical machine in your target audience. Of course there is no one target audience in that sense. Some people will have the newest MSI runtimes and other people won’t. If you aren’t sure that your target audience has the required MSI runtime, there are a couple options that you have as a setup author:
- Provide a link to the MSI runtime on your web site. While this sounds nice, in practice its frustrating for users because they may have downloaded your package earlier and not checked the prerequisites for the package. Then they try to install your package later only to find out that they need an updated MSI runtime. They’ve forgotten the URL for the site where they downloaded your package and it may be difficult to find the right thing on the Microsoft web site. So you’ve helped some users by making their download smaller (they didn’t have to download the MSI runtime bootstrapper), but you’ve hindered some other users by making your package more difficult to install because its not self-contained with respect to its dependencies.
- Use an EXE stub to examine the runtime version and download the bootstrapper when necessary. This provides the self-contained aspect at a minimal impact to those users that already have the necessary runtime.
- Use an EXE stub to examine the runtime version and install the runtime if necessary. The runtime bootstrapper is always packaged with your product. This can be a reasonable choice if your product is distributed on physical media and it is likely that your customers are installing the software on machine that are not connected to the internet. Not connected to the internet? Who has a machine like that? Well, for highly secured environments it is unusual that the machines are connected directly to the internet. The military market is the largest example of such machines, but they crop up in other environments as well.
Presumably the thing that Philip doesn’t like is the fact that packages including this EXE stub cause him extra download time. Of course the flip side of the coin is people who are frustrated by packages that are not self-contained. Option 2 above might be a reasonable compromise.
Use a .EXE-stub that checks for availability and thereafter installs a bunch of prerequisites – sometimes even other MSI packages.
I’ve done this in setup packages I’ve worked on and I’ve given the advice of using an EXE bootstrapper like this on many occasions. For some reason people want to treat MSI — a technology for installing applications — as a kitchen sink deployment solution for every kind of deployment problem that they might face, including OS service packs required by their application. But none of these extra tasks are within the scope of Windows Installer. Windows Installer is for installing applications, not handling prerequisites and their proper order of installation, or operating system service packs and so-on. You can’t simultaneously rail on Windows Installer for being too large and too complex and then complain that its not complex enough.
However, dealing with prerequisites and their order of installation is a common problem faced by setup developers. Microsoft did create the “Microsoft Component Installer Software Development Kit for Windows” which provides a way for you to declare the prerequisites that your application needs and install them from local media or from the web. The downside to this solution is that it only works for a specific list of prerequisites supported by the SDK and can’t be extended to other prerequisites your application may have, even if those prerequisites come from Microsoft. For instance, DirectX applications may have dependencies on optional components that are not part of the core runtime. These components are not supplied as merge modules, but as optional CAB files for use with the DirectSetup API. I have written a white paper on a web-based installer for DirectX applications that deals with these issues, but the Component Installer SDK doesn’t address them. But hey, its better than nothing, and if your application only depends on the components supported by this SDK, this is a great way to deal with the prerequisites issue that doesn’t require writing your own bootstrapper.
I don’t understand the problem Philip has with bootstrappers or why this is a headache for end users, provided that the bootstrappers work properly. But then again, any piece of software that doesn’t work properly is a headache for end users and installers are no different. Installers do have the unfortunate property of giving the entire product a black eye and right in the beginning of the user’s experience with the product. This is just more of an argument for why installers should be developed early and tested incrementally with your product on a daily basis. Best practices for install develpment is something I should write about, but that’s a whole other blog post.
Create a MSI-file which contains a traditional .EXE-Setup, unpack that to a temporary location and run it.
This is definately a scumbag way of creating an installation for an application and sticking it inside an MSI. But why is Windows Installer to blame for the scummy development practices of people who write shitty installers? There is definately blame to be assessed for this practice, but it doesn’t make any sense to blame Microsoft or Windows Installer for the shoddy development practices of others. Its not like the MSI documentation recommends this practice or even discusses it. Anyone who proposed doing this in any public newsgroup or forum would be ridiculed just for mentioning it.
Create MSI-files that extract a vendor specific DLL, a setup script and all files to deploy (or even just an archive) and then use that vendor specific DLL to run the install script.
This is similar to the above; its a shoddy development practice, just a different one. This practice is recommended by an installation technology vendor, but its not Microsoft. No, the fault here goes entirely to InstallShield. Their legacy InstallScript scripting language is the kind of technique that Philip refers to above. They use a few MSI custom actions to hook their scripting engine into the install process and call your script at various points in the install sequence. You can use their product to create MSI based installs that don’t use any of this crap, but if you do buy into using InstallScript in a serious way, then they have you by the balls through “vendor lock-in”, which is why they keep recommending to people that they do this. Its a stupid idea and totally unnecessary in the MSI world.
Create a custom installer that installs all files and registry keys and then launch the windows installer with a temporary .MSI-file to register your installation work in the MSI-installer.
This is also similar to the last two gripes; a poor development practice that has nothing to do with Windows Installer. Windows Installer is flexible and such shenanigans can be performed through its customization points, but it just goes to show the truth in the old adage that poor programmers write shitty code in any language.
Philip seems to think that because people can write poor installers that this is somehow the fault of Windows Installer itself. Well, if that logic were applied uniformly, then there wouldn’t be any good programming languages because poor programmers can write shitty code in any language. Windows Installer isn’t perfect; it has quirks that I don’t like, the occasional bug, and features that I wish it had to make my life easier. However, there are significant advantages to Windows Installer’s declarative approach to application installation that just can’t be had with the procedural approach of scripted installs that came before it.
Philip says that his examples of bad installation practices that he’s encountered are examples of why Windows Installer isn’t used for serious or large applications. To that I’d have to disagree. I’ve used it for serious and large installations since Windows Installer was at version 1.2 in the 1999/2000 time frame (at least that’s what my fuzzy memory recalls).
At my current employer, I’ve worked on the installation for a very large product. Its localized into 10 languages. It installs many, many files. It installs COM objects, .NET assemblies, NTFS shares, Windows Services, IIS virtual directories, web services and lots of other things. I think about the only system-wide resource type that we don’t install is a font or an ODBC configuration. I was the first person to author an upgrade path for this large, complex application. There were times when it wasn’t pretty, but all of the ugliness had to do with poor development practices we had in the past or bugs in our previous installs that hampered upgrades. We found mechanisms for coping with those defects and poor practices, usually within the context of Windows Installer itself, but sometimes they had to be worked into our setup bootstrapper. If we hadn’t had a setup bootstrapper already, we would have needed to create one in order to handle the problems that could result from failed upgrades. It was a little hairy, I’ll be the first to admit, but the problems were entirely of our own making and not the fault of Windows Installer itself.
So Philip and I agree completely about the bad practices of setup developers. Where we disagree is where to lay the blame. I blame the authors. Philip seems inclined to blame the tool.