views:

140

answers:

2

I'm currently learning the vagaries of WiX and Windows installer and I've hit a stumbling block.

The project that I'm currently packaging is made up of six discrete chunks. For now let's call them A, B, C, D, E, and F.

Chunk A is a set of common libraries and utilities that are used by every other project. It does not present any end-user functionality.

Chunk B is another set of common libraries and utilities that require functionality provided by Chunk A. This seems odd, but the architecture is beyond my ability to influence or control.

Chunk C is a third set of common libraries and utilities that require functionality provided by chunks A and B. This seems even more odd than before, but I still have no ability to change this.

Chunks D, E, and F, all require the functionality provided by chunks A, B, and C.

If possible, I would like to make sure that there is only one installation of chunks A, B, and C, that are shared across the installations of D, E, and F. I have been given the assurance that chunks A, B, and C will retain stable APIs so that they may be upgraded without breaking the functionality of D, E, or F.

My immediate thought is to create merge modules for the components in A, B, and C, then reference them in the features provided by the separate installers for D, E, and F. This would bloat up the installers, but it would guarantee that the necessary components are installed. Unfortunately, I fear that it would cause problems inside the Windows Installer validation when upgrading.

Another thought that I had was to make a single installer for A, B, and C and require it in the installers for D, E, and F via a ComponentSearch.

Does either idea make sense? If neither idea makes sense, do you have any recommendations for a correct way to do it?

+1  A: 

Include A+B+C with every installer, and install to common files. Windows Installer will handle the reference counting so that only one copy will exist on disk and remain until the last product is removed. Upgrading will be fine, Windows Installer is designed for this sort of thing :)

However, rather than Merge Modules, I suggest using Wixlibs

sascha
If I use heat to initially generate the wix files for A, B, and C, should I use a fragment or module template for the files that I intend to roll into wixlibs?
dskiles
Fragment (or no template). Product and module adds extra stuff you probably don't want.
sascha
+1  A: 

I have been given the assurance that chunks A, B, and C will retain stable APIs so that they may be upgraded without breaking the functionality of D, E,enter code here or F.

A stable API may not be enough. What if an application accidentally relies on behavior which is an undocumented coincidence (such as the order of items in a returned list), or worse, on behavior which is actually a bug? An upgrade of the shared components may then break your application because it was not tested against the upgraded components.

My immediate thought is to create merge modules ... I fear that it would cause problems inside the Windows Installer validation when upgrading.

You may be right that there are serviceability issues with merge modules. Microsoft no longer distributes new merge modules themselves. It is also notoriously difficult to create upgradeable components and still follow the Windows Installer Component Rules.

I prefer to actually install "shared" components into each application's bin folder separately. I do create wixlibs for these components, so that they can be shared between the application installers. Inside the wixlib files, I put the component in a <DirectoryRef Id="SharedComponentFolder>. This directory reference is left undefined, which is not a problem for lit.exe. In the application installers, I then alias the application bin folder like this:

<Directory Id="AppBinFolder" Name="bin">
   <Directory Id="SharedComponent1Folder" /> <!-- alias for AppBinFolder -->
   <Directory Id="SharedComponent2Folder" /> <!-- another alias -->
</Directory>

As a result, the applications have their dependencies in their own bin folder and remain isolated from each other. There is a trade-off of course:

  • you gain stability because your application always runs against the exact version of the dependencies it is tested against; no DLL Hell issues.
  • you have more work when a shared component is updated; each application installer needs to be updated and redistributed, rather than just one installer for the shared component.
  • you lose disk space (because the shared components are installed multiple times).

With .NET assemblies, the story can become even more complicated with the GAC, strong names, policy file redirects etc. But this post is already running too long :-)

Wim Coenen

related questions