views:

236

answers:

2

This is more of a philosophical question, perhaps.

Let's say I have a framework of some sort and I decide to provide a .NET library that makes the use of certain aspects of the framework easier. I don't want each application that uses the framework to carry a copy of the library locally, so I want it in the GAC (even with all the maintenance issues that that might imply.)

I can have the framework install the library into the GAC pretty easily so each app doesn't have to. But then when I create a new version of the library, my framework installer has to carry both the old and the new library to make sure upgrades don't remove the old library that might be in use by some application.

However, if each application also installs the library to the GAC, Windows Installer reference counting kicks in, and my framework no longer has to worry about carrying old libraries around in the upgrade scenario. An in-use library will only get uninstalled when the last Windows Installer reference is gone.

Obviously, each application has access to the library at the time the application is built and can easily include it in its installer.

Does anybody have an opinion/viewpoint/experience of one vs. the other? I realize this is not strictly the desired type of question (since it invites discussion), but I think a short discussion would be useful.

+1  A: 

We also have this exact need for multiple products, and for our framework we just use an MSI merge module, which is referenced in each product.

<Feature ...>
  ...
  <MergeRef Id="FrameworkMergeModule" />
</Feature>
...
<Directory ...>
  <Merge Id="FrameworkMergeModule" SourceFile="..\Tools\Framework.msm" ... />
</Directory>

Have found no problems with this approach, as you said, reference counting does its job.

There are extra hoops to jump through to get assemblies into the GAC (strong naming, a little more work in wix) but nothing major. This approach works if you use the GAC or just do plain xcopy deployment into the install directory (via wix-fu)

The main pain we felt (after strong naming an assembly) using was not understanding AssemblyVersion and AssemblyFileVersion attributes fully before diving in...you really only want to change AssemblyVersion when there is a genuine need, and look into wildcard referencing for Build and/Or Revision versions to make things a little easier (assuming you have a disciplined versioning strategy)

Si
A: 

Is each new version of your framework backward compatible? Do you ever deprecate components or change interfaces?

Assuming NO to the questions above, you could increment the versions, have the new library uninstall the old version and install the new one. Then use a GAC Policy file to map the old version to the new version. That way, applications referencing the old library, would not have to change, and would be mapped to the new version.

Here is a SO questions about creating Policy Files

MS documentation on publisher policy files

The following would force any application referencing 1.0.0.0 to use the newer 2.0.0.0. I believe you can also use wildcards.

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="myAssembly"
                       publicKeyToken="32ab4ba45e0a69a1"
                       culture="en-us" />
                <!-- Redirecting to version 2.0.0.0 of the assembly. -->
                <bindingRedirect oldVersion="1.0.0.0"
                      newVersion="2.0.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>
Mike Ohlsen