About Windows Installer, the .NET Framework, and Visual Studio.
These days it’s more common to install products composed of more than one installer package. Modern applications are often a loose fitting of localized components and being authored into a single package just isn’t practical.
For example, a localized application will undoubtedly have neutral or single-language binaries while using satellite resources for other languages’ resources. You could package these common binaries into separate fully-localized installer packages – one for each language – but that will lead to all sorts of problems with shared components.
Having separate packages for common components (core) and for each language’s resources often yields a better installer architecture. Rather than producing, testing, and publishing patches for each fully-localized product (or one patch for all languages, which still requires the same amount of testing), you’ll most often only need to produce a single patch for the common package. Language resources will probably be changed little over the course of an application’s lifetime.
Shared prerequisites like runtimes, third party controls, and the like are also often separate packages you may need to install since merge modules are not separately serviceable and also install shared components.
While this common architecture solves a number of problems, it certainly introduces more problems. For example, if a user installs multiple languages of the same product on the same machine, how do you avoid uninstalling the core packages until the last language is uninstalled? Likewise, if a product is uninstalled will it takes any shared prerequisites with it that other products still require? How do you know if other products still require any packages?
That’s where package reference counting comes in.
Package reference counting, or just ref-counting, is an old design I’ve finally put into practice in recent versions of the Windows Installer XML (WiX) chainer, Burn. The design, however, can – and should – be utilized by any chainer or package that works on a simple premise: you need to opt-into the system or your packages could be prematurely uninstalled.
The idea is simple and probably best reflected in the following example. Let’s say you are installing package B that depends on shared package A. Product C is a third party product that also depends on A, but you’re not really aware of that (as is common). You may think other package depend on A, but don’t know which ones. If both package B and C utilize package ref-counting, you don’t have to worry about package A being uninstalled prematurely.
This feature also allows package A to be upgraded and, as long as they follow the rules I’ll discuss more in future posts, will simply migrate any existing dependents during the upgrade. So if packages B and C dependent on package Av1 and later Av2 is released packages B and C will still be protected.
I’ll go into more details about how to author this in WiX, how other installer technologies can implement and support this feature, and how it’s being utilized today in future posts.
I'm very interested in the details of your solution since I'd like to have sth. similar in the setup bootstrapper of my company.
In my opinion, uninstallers that leave their addon packages behind are one of the most annoying things for the users. Often they can't even manually clean up, since they cannot be sure if this would damage other products which might still have a dependency on the addon packages.
@Sascha, glad to hear it! The intent was to provide a generic solution that all bootstrappers could implement so that the whole deployment ecosystem works well regardless of technology.
I'll have a post soon that explains it in more depth with some follow-up posts on other supported scenarios, how you should author packages, and more. Stay tuned!
Still did not get around to start implementing my own solution but I'd rather take an existing, well thought out approach anyway.
If you don't have enough time for writing a full-fledged article yet, could you give a hint where to look in the WiX source code?
Thank you very much
@Sascha, thanks for the interest and sorry I haven't posted more about the implementation. I've got a start on a post but have been fairly busy lately (partly working on other WiX features like automatic slipstreaming and sticky patching).
In the WiX source (http://wix.sourceforge.net), see src\ext\DependencyExtension. There's actually a static lib that gets built called deputil.lib you can use, and the registry layout you can find under the wixlib subfolder as WiX authoring. It's a fairly simple design and shouldn't be hard to implement.
In fact, at a minimum a chainer or another installer package (ex: MSI) just has to write a couple of registry keys and values and as long as the MSI being ref-counted has the right custom action scheduled (you could just reuse the WiX CA in the aforementioned extension without writing anything yourself - which pulls in the right properties so that there's a standard approach) that's really all that's needed. A non-conforming chainer would be led to believe a ref-counted MSI was removed successfully when, in fact, it may not be if other references remain (assuming the chainer doesn't do any sort of post-uninstall check, which is uncommon).