Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#

.pdf
Скачиваний:
173
Добавлен:
12.02.2016
Размер:
16.87 Mб
Скачать

Module 4: Deployment and Versioning

17

 

 

 

A Strong-Named Assembly

 

 

 

 

 

 

 

 

 

 

Topic Objective

 

 

 

 

 

! Global Assembly Cache

 

 

To discuss the problems

 

 

 

 

 

 

 

 

 

 

 

 

 

that may occur when

 

 

 

 

# Contains assemblies shared by unrelated applications

 

 

multiple applications share

 

 

 

 

! Strong Names Are Required for Assemblies in the Cache

 

 

components, and to

 

 

 

 

 

 

introduce the use of strong

 

 

 

 

# Generate a public-private key pair:

 

 

names.

 

 

 

 

 

 

 

 

 

 

 

sn

 

–k orgKey.snk

 

 

Lead-in

 

 

sn

 

–k orgKey.snk

 

 

 

 

 

 

 

# Add code to source file to specify version and key information:

 

 

The client applications

 

 

 

 

 

 

discussed in the preceding

 

 

 

 

 

 

 

 

topics are limited in that they

 

#if

 

STRONG

 

 

 

 

#if

STRONG

 

 

only illustrate the use of

 

[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]

 

 

 

 

[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]

 

 

assemblies that are private

 

[assembly: System.Reflection.AssemblyKeyFile("orgKey.snk")]

 

 

 

 

[assembly: System.Reflection.AssemblyKeyFile("orgKey.snk")]

 

 

 

#endif

 

 

to the Client.exe and do not

 

 

#endif

 

 

demonstrate the use of

 

 

 

 

# Compile:

 

 

assemblies that are shared

 

 

 

 

 

 

 

 

csc /define:STRONG /target:library /out:AReverser.dll!

 

 

by more than one

 

 

csc /define:STRONG /target:library /out:AReverser.dll!

 

 

 

 

AReverser.cs

 

 

application.

 

 

 

AReverser.cs

 

 

 

 

 

 

 

 

*****************************ILLEGAL FOR NON-TRAINER USE******************************

The client applications discussed in the preceding topics show the basics for constructing a complex program, but they are limited in that they only illustrate the use of assemblies that are private to the Client.exe and do not demonstrate the use of assemblies that are shared by more than one application.

This topic discusses the problems that may occur when multiple applications share components. It then introduces the use of strong names, the .NET Framework solution to these problems.

Issues with Sharing Components

Many applications use assemblies that are shared by more than one application. These shared assemblies, which are typically provided by third-party developers, are installed in a common location on the system, the global assembly cache. By default, the system looks for each application’s assemblies in the global assembly cache.

In classic COM and COM+ applications, the sharing mechanism depends heavily on the Windows System Registry in which information about each component, including its version and physical file location, is stored. This mechanism allows multiple applications to share a single component, but it also allows a component of a newly installed application to replace an existing component and possibly cause other applications to break.

Such overwriting of existing components is often difficult to detect because the application that is causing the problem appears to work properly.

18

Module 4: Deployment and Versioning

Strong Names

In the .NET Framework, you can solve the problems that are caused by the sharing of components with multiple applications by more strongly associating a distinct build of a component assembly with the client application. A distinct build is indicated by a combination of a version number and a special value that is called the publicKeyToken.

Important Strong names provide a strong integrity check. Passing the .NET Framework security checks guarantees that the contents of the assembly have not been changed since it was built. Note, however, that strong names in and of themselves do not imply a level of trust, such as that provided by a digital signature and supporting certificate.

When component assemblies are associated with a distinct build, the system can isolate these component assemblies, thus allowing different versions to run at the same time for different client applications. This system of protection is sometimes called side-by-side execution. It differs from backward compatibility because with side-by-side execution, applications can run alongside other versions of the same applications without affecting their respective execution environments.

You can facilitate side-by-side execution by assigning strong names to your assemblies. A strong name consists of the assembly’s identity, which includes its simple text name, version number, and culture information, if provided, and a public key.

To demonstrate these additional build attributes the client and component scenario is extended by adding an assembly named AReverser. This assembly contains a class with a method that is named Invert, which uses the System.Array.Reverse method to reverse an array of strings.

Note The code details of AReverser are not relevant to deployment issues and therefore are not shown. This module’s lab contains the complete code details.

Building the Assembly Without a Strong Name

You begin by building the new component assembly without specifying any options to make it have a strong name. First, you compile the new AReverser assembly, as follows:

csc /target:library /out:AReverser.dll AReverser.cs

After compiling the new AReverser assembly, you can examine the metadata by using the MSIL disassembler. The MSIL disassembler indicates that the assembly does not have an established version number, as shown in the following code:

.assembly AReverser

{...

.hash algorithm 0x00008004

.ver 0:0:0:0

}

.module AReverser.dll

Module 4: Deployment and Versioning

19

 

 

 

Generating a Public-Private Key Pair

To create an assembly with a strong name, you must compile the assembly by using a private key. Public keys are used for verification. Therefore, before compiling the assembly, you must first generate a public-private key pair. You use the Strong Name tool (Sn.exe) to generate a new key pair and place them in a file, as in the following example:

sn –k orgKey.snk

Compiling a Strong-Named Assembly

Now that you have a private key, you are ready to compile the component, specifying the key file and the version number to be assigned. You can do this by specifying AssemblyVersion and AssemblyKeyFile attributes in the AReverser.cs file using the STRONG conditional compilation symbol:

#if STRONG

[assembly: System.Reflection.AssemblyVersion("1.0.0.0")] [assembly: System.Reflection.AssemblyKeyFile("orgKey.snk")] #endif

You must then define STRONG in the compile process:

csc /define:STRONG /target:library /out:AReverser.dll! AReverser.cs

If you run the MSIL disassembler again on AReverser.dll, you can verify that the assembly is now strong-named from the presence of a .publickey property and a non-default version, which is specified by the .ver property of 1:0:0:0.

The following example shows the disassembled code:

.assembly AReverser

{

...

.publickey = (00 ... 71 8A 7D 6A D7 )

.hash algorithm 0x00008004

.ver 1:0:0:0

}

.module AReverser.dll

For more information about the Strong Name tool, see Packaging and

Deployment Tools in this module.

20

Module 4: Deployment and Versioning

Deploying Shared Components

Topic Objective

To explain the commands that are used to install, examine, and remove assemblies from the global assembly cache.

Lead-in

While components can easily be shared by related applications by putting them in a common subdirectory, shared assemblies that are used by many applications on the system are often stored in the system’s global assembly cache.

!Installing the Strong-Named Component in the Global Assembly Cache

gacutil /i AReverser.dll gacutil /i AReverser.dll

! Examining the Global Assembly Cache

gacutil /l gacutil /l

! Removing a Shared Component File

gacutil /u AReverser gacutil /u AReverser

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Deployment with strong-named assemblies is usually more complicated than deployment with assemblies that are not strong-named. While components can easily be shared by related applications by putting them in a common subdirectory, shared assemblies that are used by many applications on the system are often stored in the system’s global assembly cache.

As with the previous examples of componentized applications, this revised Client.exe can run directly from a file server on any workstation on which the

.NET runtime is installed. The Client.exe and Stringer.dll files can also be copied to a local volume.

Installing a Strong-Named Assembly into the Global Assembly Cache

Installing the strong-named component into the global assembly cache requires the following additional command on the computer that will be running the corresponding Client.exe program:

gacutil /i AReverser.dll

Note You must have Administrator privileges on a computer to install assemblies into the global assembly cache. Assemblies that are installed in the global assembly cache must have a strong name.

After installing the AReverser assembly, you can then examine the system assembly cache by typing:

gacutil /l

Module 4: Deployment and Versioning

21

 

 

 

The output of this command is:

...

AReverser, Version=1.0.0.0, Culture=neutral, PublicKeyToken=!

0588613cb04b772e, Custom=null

...

You can also examine the system assembly cache by navigating to the \WindowsDirectory\Assembly directory and by using the cache shell extension.

Uninstalling a Strong-Named Assembly from the System Cache

Cleaning up applications that use strong-named assemblies requires more work than cleaning up the simple applications or componentized applications that are described in the preceding topics. In addition to deleting the executable files, you should remove the shared component file from the global assembly cache since the global assembly cache is not automatically scavenged.

To remove a shared component file, an administrator can use the cache shell extension, select the appropriate components, and delete them. Developers and administrators who want to automate the process, however, should use the command-line interface to the assembly cache manager as follows:

gacutil /u AReverser

To confirm the removal, you can view the contents of the global assembly cache by using the following command:

gacutil /l

For more information about installing and uninstalling shared assemblies to the global assembly cache, see Packaging and Deployment Tools in this module.

22

Module 4: Deployment and Versioning

A Versioned Assembly

Topic Objective

To discuss the physical representation and logical mapping of the compatibility version number.

Lead-in

The final packaging and deployment example in this module involves updating the shared assembly to a new version.

!Applications Need to Bind to a Suitable Version of a Shared Assembly

!The Version Number Is Represented by a 4-Part Number

<major version>.<minor version>.<revision>.<build number> <major version>.<minor version>.<revision>.<build number>

!Applications Get the Versions of Assemblies with Which They Were Built and Tested

#Unless overridden by explicit policy rules

*****************************ILLEGAL FOR NON-TRAINER USE******************************

The final packaging and deployment example in this module involves updating the shared assembly to a new version. In Creating Multiple Versions of a Strong-Named Assembly in this module, the shared assembly is updated to deliberately break compatibility with the client and to demonstrate how the

.NET Framework allows you to configure the client application to bind to the desired version of the shared assembly.

Versioning

Each assembly has a specific compatibility version number as part of its identity. As such, two assemblies that differ by compatibility version are completely different assemblies as far as the .NET runtime class loader is concerned.

This compatibility version number is physically represented as a four-part number with the following format:

<major version>.<minor version>.<revision>.<build number>

Module 4: Deployment and Versioning

23

 

 

 

Each segment of this number has a specific meaning to the .NET runtime as it decides which version of an assembly to load. Logically, the compatibility version number has three parts, with the following meanings:

1.Incompatible

A change has been made to the assembly that is known to be incompatible with previous versions.

Example: Major new release of the product

2.Maybe Compatible

A change has been made to the assembly that is thought to be compatible and carries less risk than an incompatible change. However, backward compatibility is not guaranteed.

Example: Service Pack or release of a new daily build

3.Quick Fix Engineering (QFE)

An engineering fix that customers may want to upgrade to. Example: An emergency security fix

These three logical parts correspond to the physical four-part version number as follows:

For example, an assembly with compatibility version number 2.0.0.0 is considered incompatible with an assembly whose compatibility number is 1.0.0.0. Compatibility number 2.0.2.11 is considered a QFE to compatibility number 2.0.2.1.

24

Module 4: Deployment and Versioning

Creating Multiple Versions of a Strong-Named Assembly

Topic Objective

To explain how to create multiple versions of a shared component by using strong-named assemblies.

Lead-in

In the .NET Framework, you can solve the problems that are inherent in working with multiple versions of a shared component by using strong-named assemblies.

! Building Two New Versions of AReverser with a New Key Pair

#Specify version 2.0.0.0 for one and 2.0.1.0 for the other For AReverser_v2.0.0.0\AReverser.cs:

#if STRONG #if STRONG

[assembly: System.Reflection.AssemblyVersion("2.0.0.0")] [assembly: System.Reflection.AssemblyVersion("2.0.0.0")] [assembly: System.Reflection.AssemblyKeyFile("orgVerKey.snk")] [assembly: System.Reflection.AssemblyKeyFile("orgVerKey.snk")] #endif

#endif

! Build

csc /define:STRONG /target:library! csc /define:STRONG /target:library! /out:AReverser_v2.0.0.0\AReverser.dll!

/out:AReverser_v2.0.0.0\AReverser.dll! AReverser_v2.0.0.0\AReverser.cs AReverser_v2.0.0.0\AReverser.cs

!Use Ildasm.exe to Examine Different Versions

#Note the publickey and version numbers

.assembly AReverser

.assembly AReverser

{ ...

{ ...

.publickey = (00 24 ... 82 B1 F2 A0 )

.publickey = (00 24 ... 82 B1 F2 A0 )

.hash algorithm 0x00008004

.hash algorithm 0x00008004

.ver 2:0:1:0

.ver 2:0:1:0

*****************************ILLEGAL FOR NON-TRAINER USE******************************

In the .NET Framework, you can solve the problems that are inherent in working with multiple versions of a shared component by using strong-named assemblies. This topic examines how multiple versions of an assembly are created.

Building on the code in the preceding strong-named AReverser assembly, two separate versions of the strong-named component are created, and additional application configuration options are used to show how an application can be made to run. A method in version 2.0.1.0 of AReverser.dll is deliberately made incompatible with the same method in version 2.0.0.0 so that a client that successfully calls the method that is using version 2.0.0.0 will fail with the later revision.

Versioning keys can change from one version of an assembly to the next. To illustrate this, you generate a new key pair using the Strong Name (Sn.exe) tool and place that new key pair in a file, as follows:

sn –k orgVerKey.snk

After creating a new private key, you add the following to the AReverser.cs file in the AReverser_v2.0.0.0 subdirectory:

#if STRONG

[assembly: System.Reflection.AssemblyVersion("2.0.0.0")] [assembly: System.Reflection.AssemblyKeyFile("orgVerKey.snk")] #endif

Module 4: Deployment and Versioning

25

 

 

 

You add the following to the AReverser.cs file in the AReverser_v2.0.1.0 subdirectory:

#if STRONG

[assembly: System.Reflection.AssemblyVersion("2.0.1.0")] [assembly: System.Reflection.AssemblyKeyFile("orgVerKey.snk")] #endif

You compile both of these versions by using the commands:

csc /define:STRONG /target:library! /out:AReverser_v2.0.0.0\AReverser.dll! AReverser_v2.0.0.0\AReverser.cs

csc /define:STRONG /target:library! /out:AReverser_v2.0.1.0\AReverser.dll! AReverser_v2.0.1.0\AReverser.cs

If you run the MSIL disassembler on these two updated files, you can verify that the assemblies are strong-named as indicated by the version number, 2.0.0.0 or 2.0.1.0, depending on which one you inspect with the MSIL disassembler.

Notice that these two assemblies have the same publickey property, but the value of this property is different than the previous version 1.0.0.0 AReverser.dll. This property is different because a different key pair was used, orgVerKey.snk, instead of orgKey.snk.

The following example shows the MSIL disassembler output for version 2.0.1.0 of the AReverser.dll:

.assembly AReverser

{

...

.publickey = (00 24 ... 82 B1 F2 A0 )

.hash algorithm 0x00008004

.ver 2:0:1:0

}

26

Module 4: Deployment and Versioning

Binding Policy

Topic Objective

To discuss binding policy.

Lead-in

Whenever the .NET Framework is asked to bind to a specific version of a shared assembly, the version of the assembly reference may be altered at several policy-resolution stages before the .NET Framework finally decides to which version to bind.

!Policy Resolution

#Allows an assembly reference, specified at compile time, to be modified after the application has been deployed without recompiling

!Happens in the Following Stages:

1.Application-policy resolution

2.Publisher-policy resolution

3.Administrator-policy resolution

!In Each Stage, an XML Configuration File Is Read

# Note: XML is case-sensitive

!Version Numbers of Assemblies That Are Not Strong-Named Are Not Checked

!Configuration File Tag Examples

#privatePath

#bindingRedirect

*****************************ILLEGAL FOR NON-TRAINER USE******************************

When the .NET Framework is asked to bind to a specific version of a shared assembly, the version of the assembly reference may be altered at several policy-resolution stages before the .NET Framework finally decides which version to bind to. This policy-resolution process allows an assembly reference, which is specified at compile time, to be modified after the application has been deployed, without recompiling the assemblies involved.

Policy resolution happens in the following three stages:

1.Application-policy resolution

2.Publisher-policy resolution

3.Administrator-policy resolution

In each stage, an XML configuration file that describes the policy is read. The privatePath attribute in the application-configuration file illustrates the simplest form of application-policy resolution. In addition, the bindingRedirect tag can be used to redirect the reference to a different version of a shared assembly.

Note The version numbers of assemblies that are not strong-named are not checked.

Соседние файлы в папке c#