Private and Shared Assemblies


Up to now you have been dealing only with private assemblies — assemblies that are deployed as part of a single application. However, the .NET Framework also has special facilities to provide for shared assemblies that are used by multiple programs simultaneously.

Private Assemblies

By default, an assembly is private to your project. Private assemblies must be in the same directory as the application.

The Shapes.dll assembly is private; in order to refer to it from the ShapeUser project you had to browse into the Shapes development directory from the ShapeUser project when adding the reference in Visual Studio 2005 — in which case Visual Studio 2005 makes a private copy of Shapes.dll and places it in the ShapeUser directory.

Copying the Shapes.dll assembly ensures that ShapeUser can execute even if the original Shapes.dll is unavailable because of ongoing development. However, making copies of every referenced DLL is not very efficient for widely used components, so the .NET Framework provides for shared assemblies.

Shared Assemblies

Shared assemblies are available for use by all the programs on the system. A program does not need to know the location of a shared assembly because all shared assemblies are stored in a special .NET system directory called the Global Assembly Cache (GAC). Because they are available systemwide, the .NET runtime imposes several extra checks on shared assemblies to ensure that they are valid for the program requesting them, such as security and version compatibility.

Strong Names

A shared assembly must have some means of distinguishing it from other assemblies that may have the same name. Also, for assemblies shared across the system, it is desirable for security to have a means of uniquely identifying an assembly as originating from you, the developer, and prevent the assembly from being replaced with another assembly using the same name and version, or prevent it from being altered in any way, for example by a virus.

Requiring that a shared assembly be signed with a cryptographic key does this. The key uniquely identifies your assembly and protects not only against a security breach but also against a simple name/version collision due to two components having the same name and version number.

Note

If the keys are different, the components are considered to be different even if they have the same name.

The unique combination of the assembly name, version, and key is called a strong name.

Strong names are required for shared assemblies installed with ClickOnce deployment or installed into the Global Assembly Cache, described in the next section. You do not generally want to add a strong name for an application executable, as it might interfere with that application's use of private assemblies. For example, it does not make sense for us to sign ShapeUser.exe with a strong name, but it does make sense to sign Shapes.dll with a strong name for use by multiple applications.

Global Assembly Cache

The Global Assembly Cache is a special directory, located in the WINDOWS\assembly directory (on Windows XP) or the WINNT\assembly directory (on Windows 2000/2003). All shared assemblies, including the .NET Framework System assemblies supplied by Microsoft, are located and loaded from here. If you browse this directory with the Windows Explorer, a special Windows shell extension displays the properties of the assemblies, including the key incorporated into the strong name of each.

The Windows shell extension (called shfusion.dll) plugs into Windows Explorer and extends its capabilities beyond a normal file listing. This screenshot shows the GAC viewed in Windows Explorer. The name, version, key, and other properties of the assemblies are listed in Figure 26-20.

image from book
Figure 26-20

The Windows shell extension enforces the security policy for the Global Assembly Cache, enabling assemblies to be copied into this directory via drag and drop, but only if the rules are adhered to. Let's look at the rules you have to follow to allow you to place an assembly into the Global Assembly Cache.

Creating a Shared Assembly

In order to create a shared assembly with a strong name, you must generate a public/private key pair that is used to sign an assembly. Public/private key cryptographic systems use a private key known only to the originator of the information to be encrypted, and a public key published to the world. the .NET environment uses this same mechanism to ensure that a referenced shared assembly is really the assembly wanted (assemblies from different companies could have the same name and version number, for example, or a hacker could try to spoof a program by creating an assembly with the same name/version, or try to tamper with an existing assembly). The keys in the reference to the assembly and the key in the (signed) shared assembly itself are checked to make sure they match; if they do not, the shared assembly will not load.

The combination of the assembly name, version, and public key are guaranteed to be unique; this combination is called a strong name.

the .NET Framework provides a tool for generating the strong name called sn.exe (sn stands for strong name).

Executing sn.exe from the Visual Studio Command Line

Sn.exe is an external .NET Framework utility like Ildasm. As with Ildasm, you can execute it from the Visual Studio Command Prompt. To do this, go to go the Start All Programs Microsoft Visual Studio 2005 Visual Studio Tools Visual Studio Command Prompt menu and start a command prompt to try the steps in the following Try It Out. Because you must pass command-line arguments to Sn.exe it is not really practical to add it as an external tool to Visual Studio 2005 as you did with Ildasm.

Try It Out – Signing the Shapes Assembly

image from book

Follow these steps to sign the Shapes assembly:

  1. From the command line, change the directory to C:\BegVCSharp\Chapter26\Shapes\ Shapes. Use the following command to generate a key file, giving a filename (usually with the .snk extension) that you will reference from your assembly:

    sn –k Shapes.snk 

    This creates the key file Shapes.snk in the current directory.

  2. Now, to sign Shapes.dll with this key file, right-click on the Shapes C# project in the Solution Explorer (highlighted in the Solution Explorer on the right side of Figure 26-21), and choose Properties.

    image from book
    Figure 26-21

  3. Click on to the Signing tab at the left side of the Shapes project properties, as shown in Figure 26-21. In the Key Selection area of the screen, click on the Use a Key File radio button, type in the path name to Shapes.snk (or browse to the location of Shapes.snk by choosing <Browse...> from the drop-down list — the key file will appear in the directory list with a padlock icon). Finally, check the Sign the Assembly check box; the Signing properties screen will appear as shown in Figure 26-21.

  4. Now recompile the Shapes.dll assembly. If Visual Studio 2005 can't find the Shapes.snk file, the project won't compile, and you will get an error such as:

    Cryptographic failure while signing assembly 'C:\BegVCSharp\Chapter26\Shapes\Shapes\obj\Debug\Shapes.dll' -- 'Error reading key file 'Shapes.snk' -- The system cannot find the file specified.'

    This tells you exactly where Visual Studio 2005 is looking for the key file, and you can either move the file to that directory or specify a directory relative to it.

    Once you have successfully rebuilt the project, the assembly is signed.

  5. Open up Ildasm, and examine the manifest of the Shapes.dll assembly — you can see that a public key has been generated and embedded with a .publickey statement toward the bottom of the manifest, as shown in Figure 26-22.

    image from book
    Figure 26-22

  6. You need to recompile ShapeUser.cs to update the external assembly reference inside ShapeUser.exe with the signed version of Shapes.dll. Once recompiled, it works just as before, still using the local copy of Shapes.dll.

  7. Now that your assembly is signed, you are able to install it into the Global Assembly Cache. This can be done simply by dragging and dropping the .dll file into the GAC folder located in WINDOWS\assembly (on Windows XP) or WINNT\assembly (on Windows 2000/2003), or alternatively, you can use a Visual Studio 2005 command-line tool called Gacutil (Global Assembly Cache Utility). To install Shapes.dll into the Global Assembly Cache, use the Gacutil with the /i option from a command-line prompt:

    Gacutil /i Shapes.dll

    The message "Assembly successfully added to the cache" will indicate successful installation of the assembly.

    Note

    Note that for deployment of a commercial application, the preferred way to add a shared assembly to the Global Assembly Cache is to use the Windows Installer.

  8. To prove that Shapes.dll is in the cache, delete the copy of Shapes.dll in the current directory. Now, from the command line, go to the directory containing the ShapeUser executable, which is

    C:\BegVCSharp\Chapter26\ShapeUser\ShapeUser\bin\Debug

    and run ShapeUser.exe. You should see the output:

    Area of Circle(1.0) is 3.14159265358979 

    It still runs, even with Shapes.dll absent, because it is loading the Shapes assembly from the GAC. To test this further, use Gacutil with the /u option to uninstall shapes:

    Gacutil /u shapes

    Note that the .dll extension is omitted for the uninstall option.

    Note

    Note that you must have local administrator privileges on a computer to uninstall assemblies from the Global Assembly Cache for that machine.

  9. Now try to run ShapeUser as above, and you will see the following message:

    Unhandled Exception: System.IO.FileNotFoundException: File or assembly name Shapes, or one of its dependencies, was not found.

    This shows that Shapes.dll was indeed being loaded from the GAC.

image from book

Assembly Searching

the .NET runtime follows a predefined set of rules in order to locate an external assembly when it is referenced. You have just seen how the local directory is searched first for shared assemblies, followed by the GAC.

For private assemblies, the local directory is searched first, and then the system looks for a subdirectory with the same name as the assembly. The runtime also looks for either a DLL or EXE file with the same name as the requested assembly. For the Shapes class the combination of these results in the following set of searches:

./Shapes.dll. ./Shapes/Shapes.dll ./Shapes/Shapes.exe ./Shapes.exe

If the assembly has a specific culture defined, a subdirectory with the name of the culture (for example, de for German) would be searched, also. Additional search paths or even URLs for downloading an assembly from a remote location via the Internet may be specified with a configuration file. Configuration files for an assembly are XML-format files that specify rules for the .NET runtime to apply when searching for an assembly. Configuration files can also override the default behavior for version checking. The details of configuration files and XML are quite complex and beyond the scope of this book.




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net