“DLL Hell” in .NET


I was looking at the SharePoint Services 3 video cast lately, as I need to get better versed with SharePoint 2007 and WSS 3.0. To date, I am much better versed with earlier SharePoint and some with the new SharePoint tools in Visual Studio 2010. This is really an aside to “DLL Hell”, however.

In one of the videos “Creating and Using Event Handlers in Windows SharePoint Services 3.0”, the assembly is placed in the GAC. It is here I noticed something that reminded me of one form of DLL hell in .NET. Here is the image, so you can see what I viewed:

DLLHell

Since this is the GAC, this is not really DLL Hell in the traditional sense. I will explain with a story.

In the old COM days, we had a developer that created a VB COM component that we installed in MTS (name witheld to protect the “guilty” ;->). One thing he failed to do was set the GUID for the COM component so it would regenerate under the same GUID. As the new version was dragged and dropped into MTS, a new registry entry was created with a new GUID. This worked for a few weeks until a GUID was created that came up later in the search order than the GUID he had previously created. Essentially, the highest GUID is picked and one with a lower number was created. If this does not make sense, GUIDs are not sequential by nature.

The application then failed and I found all the entries for the same COM component and deleted all but the correct GUID. I then showed him how to set the GUID in properties so it would not happen again. That is one form of traditional DLL hell. Other forms came from breaking interfaces, but that is outside of this story.

What I see here is Pattison has created three versions of LitwareFeature1 (a SharePoint feature assembly). Now, this really is not DLL Hell, in the traditional sense, as you will use four part naming in your config file (or Feature.xml, as it is set up here). You can, conceivably, use single point naming in a web.config file and end up with a bit of hell here. It does not work from the GAC, however.

Here is how the feature is named:

<Feature
    Id="32A33E3A-543F-4d69-BC87-4E1BD6EFC0A"
    Title="LitwareFeature1"
    Description="Blah blah blah"
    Scope="Web"
    Hidden="FALSE"
    ReceiverClass="LitwareFeature1.LitwareFeatureReceiver"
    ReceiverAssembly="LitwareFeature1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7ef87442c23fea66"
    xmlns="http://schemas.microsoft.com/sharepoint/"&gt;
<ElementManifests>
    <ElementManifest Location="Elements.xml" />
</ElementManifests>
</Feature>

Notice the receiver assembly. The more likely “DLL Hell” scenario here is naming the incorrect PublicKeyToken and ending up using the wrong version of the assembly.

You can alleviate this hell by keeping a single strongly named key for your organization (or at least for this project) and using it for every compile. This can lead to another form of hell, which is not incrementing the version when you stick out a newer version and having an app dependent on the old version die. If you properly version the assembly, you can end up in a different hell, which is not getting the newer version of the assembly.

In short, if you use the GAC, keep the same strong key and version when necessary. It is useful to have a list of all applications that use a particular assembly and versioning when only one application is ready for a new version of the code. If you use contract first type of development, you can avoid a lot of headaches, as you cement interfaces up front. To be safe, you should also adopt the practice of only adding to interfaces and not changing signatures of methods. This has been a rule since the COM days, so experienced developers are likely to adhere to this “rule” religiously.

Let’s sum up these rules:

  1. Determine contracts first. This not only avoids many of the hells of the changing interface, but also helps getting all teams started at the same time, as each team can write to contract.
  2. If a contract must change, make sure all teams are aware of the changes. Publish them and alert people.
  3. If a signature must change, make sure you add a new overload and keep the old version until every client using the old version is off. Mark the old version as deprecated. If this is a publicly available library, leave the deprecated version in for a few versions to ensure everyone gets off the deprecated version.
  4. Keep a single strong key for a project (whatever that means to you) and possibly only one key for the entire organization. The decision point here is whether or not part of the “business” can be sold off. In a company that does custom software, a single key shared can work. For a company that shrink wraps products, keys per product may be best so you can sell of the product or product line without selling off your key.
  5. Settle on the key for the product early and use it over and over again. Note that Pattison is doing this as a demo, so he ends up having to create multiple versions as he tours and does sessions. For your team, you should not end up with three versions of the same code base with different keys.
  6. When you come up with a new version, rather than a fix, change the version number. This will allow older apps that use four part naming to continue to use the older version even when the new version is put into the GAC.
  7. If it is not a new version, just a fix, keep the same version number. This avoids breakage and allows your apps to take advantage of the bug fixes without changing config files.

Peace and Grace,
Greg

Twitter: @gbworld
Childhood Cancer Site: http://www.crazycancertour.com

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: