Assemblies in GAC and their dependencies


Global Assembly Cache (GAC) is a machine wide central repository of shared components. For that matter maybe GAC should really be called Global Assembly Store. But for historically reason GAC is called Global Assembly Cache, and will be kept as it is in the foreseeable future.

 

Assemblies in GAC must be strongly named. Strongly name signing serves as two purposes:

  1. Integrity. CLR will be able to tell if the assembly has been tampered or not with strong name signature verification.
  1. Unique identity. Theoretically, two assemblies with the same strong name should be considered as identical.

 

An installer uses fusion GAC APIs to install assemblies to GAC, as well as uninstall them from GAC. The recommended way to install assemblies to GAC is using MSI. In the cases MSI is not an option (like the assembly is generated on the fly), you can write a custom installer using fusion’s GAC APIs.

 

Currently GAC APIs installs assemblies one at a time. There is no restriction that the assembly and its dependencies must all be in GAC, nor is there any guarantee that all the assembly’s dependencies will be in GAC. It is the application developer or component developer’s responsibility to make sure all the dependencies are installed, if this is required.

 

In the case that an assembly is in GAC, but some of its dependencies are not in GAC, it is very likely to get an assembly loading exception for applications using this assembly. To avoid this, you can re-write part of the assembly to use dynamic activation (like Activator.CreateInstance) for types in dependencies not installed in GAC, and handle the missing dependencies exception gracefully inside your assembly.

 

Comments (5)

  1. David Levine says:

    "In the case that an assembly is in GAC, but some of its dependencies are not in GAC,"

    This sounds like a questionable practice, one that is probably not intended, and which probably ought to be avoided to ensure robust systems. I can imagine the grief customers will go through if an install aborts and some of the required assemblies are missing from the GAC, especially if there are other copies of the assembly floating around the file system.

    Would it make sense to enhance the GAC API to take an set of assemblies as an argument? This would allow it to resolve all the dependencies simultaneously, and if one fails the entire operation fails.

    If that cannot be done, how about some tools that allow us to examine the GAC to ensure that it is internally consistent? i.e. that all references can be resolved with assemblies also located in the GAC.

    Thanks

  2. I agree with you that this is a very questionable practice. But the reality is, things happen. People may have implementations not suitable for sharing. That is why I recommend dynamic activation, for those types.

    The current GAC API has many deficiency. Above all there is no way to specify relations between assemblies. You can imagine we will enhance GAC API in the future.

    A tool to detect this can be very easily written. I already have a working sample. If you would like, I can post it:)

  3. Kevin Westhead says:

    Please post your sample, it would be very helpful.

  4. Kevin Westhead says:

    Also, do you know if the GAC API will be exposed through managed code in the future?

  5. Thanks for the interest. I’ll post it in another blog entry.

    There is no plan in 2.0. We decided to add one in 2.0. But then we believe we may need to change GAC API. We don’t want to add an API, only to deprecate it in the next version.

    But it is not that hard to write an managed wrapper. You may already find copies in the web.