Most Windows software developers have at some point felt the pain caused by deploying shared libraries. The .NET Framework can adapt to a number of different deployment scenarios. In the simplest scenario, the end user can copy files to a directory and go. When it's time to remove the application from the machine, the end user can remove the files, or the entire directory, if it doesn't contain any data. In this scenario there is no installer, no uninstaller, and no registry to deal with.
You can package your application for the Microsoft Installer if you want to and still deploy to a single directory, with no Registry impact.
Outside of the easy scenario, the deployment options become complex and a bit bewildering, because the problem itself is complicated. How do you enable developers to deploy new versions of shared components, while at the same time ensuring that the new version won't break an application that depends on behavior provided by a prior version? The only answer is to develop a system that allows differing versions of the same component to be deployed side-by-side.
The first thing you need to learn about deployment in the .NET Framework is that the days of deploying shared components to C:\Windows\System32 are gone. Instead, the .NET Framework includes two kinds of assemblies, well-defined rules governing how the system searches for them, and an infrastructure that supports the deployment of multiple versions of the same assembly on the same machine.
Before talking about the two kinds of assemblies, I will explain the two kinds of deployment:
Public, or Global A publicly deployed assembly is one you intend to share either among your own applications or with applications written by other people. The .NET Framework specifies a well-known location in which you are to deploy such assemblies.
Private A privately deployed assembly is one you do not intend to share. It is typically deployed to your application's base installation directory.
The type of assembly you create depends on how you intend to deploy it. The two types of assemblies are as follows:
Strong Name Assemblies A strong name assembly is digitally signed. The signature consists of the assembly's identity (name, version, and optional culture plus a key pair with public and private components). All global assemblies must be strong name assemblies. The name, version, and culture are attributes of the assembly, stored in its metadata. How you create and update these attributes depends largely on your development tools.
Everything Else There is no official name for an assembly that does not have a strong name. An assembly that does not have a strong name can only be deployed privately, and it cannot take advantage of the side-by-side versioning features of the CLR.
The key pair that completes the signing of a strong name assembly is generated by a tool provided by the .NET Framework SDK, called SN (sn.exe). SN creates a key file, which is referenced by the assembly in an attribute. The signing of an assembly can only take place when it is created, or built. However, in the form of signing called delayed signing, developers work only with the public part of the key. Later, when the final build of the assembly is prepared, the private key is added to the signature. Currently the Delphi for .NET compiler is weak on custom attributes. Because attributes are required to express the identity and reference the key file, support for strong name assemblies isn't quite complete at the time of writing.
Strong name assemblies are usually intended to be shared, so you deploy them in the Global Assembly Cache (GAC) (but they can be deployed privately as well). Because the GAC is a system folder with a specialized structure, you can't just copy the assembly there. Instead, you must use another tool contained in the .NET Framework runtime, called GACUTIL (gacutil.exe). GACUTIL installs files into and removes files from the GAC.
The GAC is a special system folder with a hierarchy that supports side-by-side deployment of assemblies, as you can see in Figure 24.4. The intent is to hide the structure of the GAC so you don't have to worry about the complexities involved. GACUTIL reads the assembly's identity from its metadata and uses that information to construct a folder within the GAC to hold the assembly.
You can see the true folder hierarchy by opening a command window and navigating to the C:\Windows\assembly directory. This hierarchy is hidden from you if you use Windows Explorer to view it.
When you create a reference to a strong name assembly in the GAC, you are creating a reference to a specific version of that assembly. If a later version of that same assembly is deployed on the machine, it will be put into a separate location in the GAC, leaving the original intact. Because your assembly referenced a specific version, that's the version it always gets.