The Manifest

The manifest is the part of the assembly that contains a list of the other elements contained in the assembly and basic identification information for the assembly. The manifest contains the largest part of the information that enables the assembly to be self-describing. Elements listed in the manifest are placed in appropriate sections. The manifest includes the sections displayed in Figure 17.2. These sections are covered later in the chapter.

Figure 17.2 Logical structure of an assembly manifest

17.2

To look at the manifest for a particular assembly, you can use the IL Disassembler (Ildasm.exe), which is included with the Windows SDK installed with Visual Studio. The version of Ildasm .exe in the SDK for .NET Framework 4.5 can examine assemblies created with earlier versions of the .NET Framework; in fact, as of release it is the same version that was released with .NET 4.0. A shortcut to ildasm.exe is no longer included on the Start menu. Instead use the All Programs ⇒ Microsoft Visual Studio 2012 ⇒ Visual Studio Tools ⇒ Developer Command Prompt for VS2012 to open a command window from which you can start ILDasm.exe. It appears that in order to simplify how many items are shown on the Start Menu (or Start screen in Windows RT), this tool has been removed from the list of available selections.

When Ildasm.exe loads, you can browse for an assembly to view by selecting File ⇒ Open. For this example and screenshots the sample code from Chapter 6 will be used. Once an assembly has been loaded into Ildasm.exe, it disassembles the metadata contained within the assembly and presents you with a tree-view layout of the data. Initially, the tree view shows only top-level elements, as illustrated in Figure 17.3. This example has only one namespace element in the tree, but if an assembly contains classes in more than one namespace, then additional elements will be shown.

Figure 17.3 ILDasm window

17.3

The full path of the assembly you are viewing represents the root node. The first node below the root is called MANIFEST; and as you've probably guessed, it contains all the information about the assembly's manifest. If you double-click this node, a new window is displayed with the information contained within the manifest. The manifest for a complex assembly can be rather long. For this example, three sections of a manifest are shown in Figures 17.4, 17.5, and 17.6. Figure 17.4 shows the top of the manifest, which contains the external references needed by this assembly, such as other .NET assemblies on which this assembly depends. If the assembly depended on COM libraries, those will be shown as external modules and listed before the external assemblies.

Figure 17.4 Accessing the manifest from ILDasm

17.4

Figure 17.5 View near the bottom of the manifest

17.5

Figure 17.6 The bottom of the manifest

17.6

Figure 17.5 shows a portion of the manifest further down, containing the beginning of the section for the actual assembly. The first items listed in the manifest for the assembly itself are the attributes that apply to the assembly. Further down, shown in Figure 17.6, are items such as resources that reside in the assembly. Keep in mind, however, that the purpose of the IL Disassembler is to allow you to review the various elements that are part of your application identity.

Assembly Identity

The manifest for an assembly also contains information used to uniquely identify the assembly. This section contains some standard information, such as the version number, and may also contain some optional elements, such as a strong name for the assembly. Assemblies come in two types: application-private and shared (differences between the two types are covered shortly), and they have slightly different identity information.

The Version Number

The manifest for an assembly contains a version number, which is indicated by the .ver directive in Ildasm.exe. Figure 17.5, shown earlier, includes a .ver directive on the bottom line in the .assembly section:

.ver 1.0.0.0

A version number contains four parts:

Major : Minor : Build : Revision

Assemblies that have the same name but different version numbers are treated as completely different assemblies. If you have an assembly on your machine that has a version number of 1.5.2.3 and another version of the same assembly with a version number of 1.6.0.1, then the CLR treats them as different assemblies. The version number of an assembly is part of what is used to define dependencies between assemblies.

Strong Names

A manifest can also contain an optional strong name for an assembly. The strong name is not a name per se, but a public key that has been generated by the author of the assembly to uniquely identify it. A strong name is used to ensure that your assembly has a unique signature compared to other assemblies that may have the same name. Strong names were introduced to combat DLL hell by providing an unambiguous way to differentiate among assemblies.

A strong name is based on public-private key encryption and creates a unique identity for your assembly. The public key is stored in the identity section of the manifest. A signature of the file containing the assembly's manifest is created and stored in the resulting EXE or DLL file. The .NET Framework uses these two signatures when resolving type references to ensure that the correct assembly is loaded at run time. A strong name is indicated in the manifest by the .publickey directive in the .assembly section.

Signing an Assembly with a Strong Name

As mentioned previously, applying a strong name to an assembly is based on public-private key encryption. The public and private keys are related, and a set is called a public-private key pair. Applying a strong name to an assembly is usually called signing the assembly with the strong name.

Visual Studio gives you a straightforward way to sign an assembly. The project's Properties page (accessed by right-clicking on a project and choosing Properties) contains a Signing tab. You simply check the CheckBox labeled “Sign the assembly” and then specify a key pair file. The drop-down for the strong name key file allows you to browse for a key pair file, or create a new one.

You can also control the signing process manually for non–Windows RT projects. The utility sn.exe can create a key pair. The utility is available from the Developer Command Prompt for VS2012. The following code shows the syntax for using sn.exe to create a key pair. Note that you need to start the command prompt window using the Run As Administrator rights in order to successfully create a new key.

sn -k pairname.snk

You should replace pairname with an appropriate name, often the name of your product or system. This will be the name of the file that is created; for example, it might be Ch17Test.snk. Note that the same key pair can be used to apply a strong name to multiple assemblies in your environment.

Once you have a key pair, you need to add it to any projects in Visual Studio that need to generate a strongly named assembly. To do that, just select “browse” from the Choose a strong name key file, then drop down and select your file's name. Figure 17.7 shows an example of the signing properties populated for a sample project.

Figure 17.7 Project Properties — Signing tab

17.7

You can also sign an assembly with a strong name by compiling at the command line. This might be the case if you want to sign the assembly outside of Visual Studio. A typical command line to compile and sign a Visual Basic assembly looks like this:

vbc /reference:Microsoft.VisualBasic.dll /reference:System.Windows.Forms.dll
/target:library /keyfile:c:mykeyskeypair.snk /out:MyAssembly.dll
/rootnamespace:MyAssembly *.vb

The separate elements of the command line have been placed on different lines for ease of reading, but they should all be on the same line in actual use. The preceding is just a template. You would need to change the /reference options to include any references needed by your assembly. You would also need to specify the correct file path for your own key pair file (.snk file) and apply your assembly and root namespace names.

Finally, strong names can be applied with a technique called delay signing. Delayed signing is helpful when assemblies need to be properly strongly named during development (so that any problems with strong names are detected at that point), but it is undesirable for all the developers to have a copy of the key pair that will be used for signing the final compiled version of the assembly. Of course, it comes at the cost of making it impossible to debug the assembly, so using the delay sign option is typically only handled near the end of the development cycle.

The Culture

The final part of an assembly's identity is its culture, which is optional. Cultures are used to define the country/language for which the assembly is targeted.

The combination of name, strong name, version number, and culture is used by the CLR to enforce version dependencies. For example, you could create one version of your assembly targeted at English users, another for German users, another for Finnish users, and so on.

Cultures can be general, as in the case of English, or more specific, as in the case of US-English. Cultures are represented by a string that can contain two parts: primary and secondary (optional). The culture for English is “en,” and the culture for US-English is “en-us.” See Chapter 15 for more about cultures in .NET.

If a culture is not indicated in the assembly, then it is assumed that the assembly can be used for any culture. Such an assembly is said to be culture neutral.

Referenced Assemblies

It was mentioned earlier that the first section of the manifest contains referenced assemblies. An assembly reference is indicated in the manifest with the .assembly extern directive (refer to Figure 17.4).

The first piece of information included is the name of the referenced assembly. Figure 17.4 shows a reference to the mscorlib assembly. This name is used to determine the name of the file that contains the actual assembly. The CLR takes the name of the assembly reference and appends .dll. For instance, in the last example, the CLR will look for a file called mscorlib.dll. The assembly mscorlib is a special assembly in .NET that contains all the definitions of the base types used in .NET, and is referenced by all assemblies.

The .publickeytoken Directive

If the assembly being referenced contains a strong name, then a hash of the public key of the referenced assembly is stored as part of the record to the external reference. This hash is stored in the manifest using the .publickeytoken directive as part of the .assembly extern section. The assembly reference shown in Figure 17.4 contains a hash of the strong name of the mscorlib assembly. The stored hash of the strong name is compared at run time to a hash of the strong name (.publickey) contained within the referenced assembly to help ensure that the correct assembly is loaded. The value of the .publickeytoken is computed by taking the lower 8 bytes of a hash (SHA1) of the strong name of the referenced assemblies.

The .ver Directive

The version of the assembly being referenced is also stored in the manifest. This version information is used with the rest of the information stored about a reference to ensure that the correct assembly is loaded (this is discussed later). If an application references version 1.1.0.0 of an assembly, it will not load version 2.1.0.0 of the assembly unless a version policy (also discussed later) exists to indicate otherwise. The version of the referenced assembly is stored in the manifest using the .ver directive as part of an .assembly extern section.

The .locale Directive

If an assembly that is being referenced has a culture, then the culture information is also stored in the external assembly reference section, using the .locale directive. The combination of name, strong name (if it exists), version number, and culture are what constitute a unique version of an assembly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset