Class libraries – shared assemblies

This post is a continuation of Class libraries – private assemblies

class library is a *.dll (dynamic link library) file containing types that can be used by external applications.

Assemblies can be private or shared. The main difference is that the same copy of the shared assembly can be used by many applications, whereas with the private assembly the .dll file simply gets copied to the client application’s directory. The advantage of shared assemblies is that they are easy to update.

For example, mscorlib.dll is not copied to each project’s directory. It is the shared assembly.

Global Assembly Cache (GAC)

GAC is a code cache that stores assemblies designated to be shared by several applications on the computer. The exact path of GAC depends on version of your .NET platform. From .NET 4.0 it is 

C:\Windows\Microsoft.NET\assembly\GAC_MSIL

Here you can find folders for well known libraries like \System.Windows.Forms or \System.Core. In GAC we can only install *.dll files. No *.exe allowed.

Strong names

Assemblies deployed in the Global Assembly Cache must have a strong name. To do it in VS, open Properties window, Signing tab. Check Sign the assembly box and choose New in the drop down list. The Create Strong Name Key pop up opens. In key file name put a *.snk (strong name key) file name. You can also add a password.

signing

From now on the myKeyPair.snk file will be visible in Solution Explorer.

snk file

In Properties window, Application tab click Assembly Information button. Here you can add more info about your assembly.

application

Installing the assembly in GAC

To install your assembly with a string name in GAC, first run DeveloperComandPrompt as administrator. Now type cd plus the bin/Debug path.

gacutil

We will use gacutil.exe which is the Global Assembly Cache tool that allows you to view and manipulate the contents of GAC. This tool is automatically installed with Visual Studio. It contains the following commands:

/i – installs in GAC the assembly with a strong name
/u – uninstalls the assembly from GAC
/l – displays assemblies installed in GAC

Use /i to install the library:

gacutil /i Animals.dll

installes

If you now check the GAC folder, you will see the Animals directory there.

gac instaled

We can now display info about our assembly with /l command. Note that with this command you skip the .dll part.

l info

Using the shared assembly

Create a new Console project. In Solution Explorer click References, Add Reference. You can choose the .dll file from the bin/Debug folder the same way as we did with a private assembly (if the assembly has a strong name, the .dll file will not get copied locally) or choose the .dll from GAC. We can now use the Lion type from Animals library. Rrrroar!

sharedInUe.png

Redirecting to a new version

If you use a shared assembly and need to update the library to a new version, good news is that there is no need to rebuild the client apps! The applications consuming your library can be dynamically redirected to the new version with a .config file.

Let’s check this out. Create a copy of a compiled library project folder. Change one of the methods to display info about the new version.

roar2

Change the version number in Properties, Assembly information.

version2

installInGACv2

Note that in GAC you now have two versions of the library. The name of each sub folders consists of the “v.4.0” which means that the library was compiled on .NET platform in version 4.0 or higher. Next we have the library version specified in Properties, Assembly information and public token key value which is a part of the strong name.

gac

We have a client application that references our Animals library and uses the Lion type.

RoarV1

So far it still use the version 1.0.0.0 of our library. How to redirect it to version 2.0.0.0?

Redirecting to the newest version using .config file

You can add a .config file to the client app bin\Debug folder. The .config file will in our case get name NewClient.exe.config. We specify the library name, publicKeyToken (which you can find in GAC in version 1 and 2 folder names or using gacutil /l Animals command), oldVersion and newVersion. The oldVersion can be also a range for example oldVersion=”1.0.0.0-1.2.0.0″.

configFile

You can add a .config file to each client app. but with many applications consuming the library that could be a nightmare for the administrators. Instead, we can use publisher policy assemblies.

Publisher policy assemblies

A publisher policy assembly is an assembly that configures the policy to be used when the .NET runtime binds to an assembly. It lets us distribute a binary version of  *.config file installed in GAC folder with the newest version of the assembly. The publisher policy assembly is installed into the GAC and is named using the policy.major_ver.minor_ver.assembly.dll convention, where major_ver and minor_ver refer to the old version of the assembly. Therefore, if you are updating version 1.0 of animals.dll to version 2.0, the publisher policy assembly name would be policy.1.0.animals.dll. Publisher policy assemblies are created in command line by assembly linker (al.exe) tool. Let’s see how to do it step by step. We will redirect all client that use animals library to use animals version 2.0.

Create a new folder (I called mine animalsPublisherPolicyAsembly) and inside it create a animals.config filewith the following xml (the same as above):

configFile

Open Developer Command Prompt in admin mode and get to the animalsPublisherPolicyAsembly folder:

cd C:\PROGRAMOWANIE\_BLOG\Libraries\animalsPublisherPolicyAsembly

Now use al.exe with the following command (including your own path to the .snk file):

al /link:animals.config /out:policy.1.0.animals.dll /keyfile:C:\PROGRAMOWANIE\_BLOG\Libraries\Animals\Animals\myKeyPair.snk

animals.config is the publisher policy file with xml redirection code we just created

policy.1.0.animals.dll is the publisher policy assembly which gets created with the command above in animalsPublisherPolicyAsembly  folder

policy folder

C:\PROGRAMOWANIE\_BLOG\Libraries\Animals\Animals\myKeyPair.snk is the path to the .snk file of the Animals library. Use your own path, of course.

Once the policy.1.0.animals.dll is created, install it in GAC:

gacutil /i policy.1.0.animals.dll

Now you can check that in GAC a new policy.1.0.animals folder got created with animals.config and policy.1.0.animals.dll files:

policy inGAC

policyinGACFiles

Now let’s check the AnimalsClient project.

animalsClient

It references Animals library in v.1.0.0.0 as we can check in the reference properties. It does not have the redirection code in it’s .config file. Yet,  when we run it, we get the version 2 result! The library got redirected to version 2.

v2

Turning off the publisher policy’s redirection

The way of redirecting the library version described above is great when you create a library and later on discover a hole in it. In this case you want all the client to use the new version! If the update is for changing functionalities, however, we may want some clients to ignore the policy’s redirection. In this case simply add a .config file to the client’s bin/Debug folder with:

<publisherPolicy apply=”no”/>

ignoreFile

With this xml we get the version 1 result again…

1

but comment the apply=”no” part…

commented

… and you get version 2 again 🙂

v2

References

C# 6.0 AND THE .NET 4.6 FRAMEWORK by A. Troelsen and P. Japikse

https://docs.microsoft.com/pl-pl/dotnet/framework/app-domains/gac

Using publisher policy assemblies

Leave a comment