Simplifies publishing and resolving DLL Hell problems with the. NET Framework

Source: Internet
Author: User
Tags include net time new features object model split versions web services visual studio
Solve | Problem Summary: This article describes the assembly concept and explains how the. NET Framework uses the assembler to solve versioning and publishing issues.


Brief introduction
Problem description
Characteristics of the solution
Assembly: Building Blocks
Versions and shares
Version Policy


Brief introduction

The Microsoft®.net framework introduces several new features designed to simplify application publishing and resolve DLL Hell. Both end users and developers are familiar with versioning and publishing issues that can be accompanied by today's component-based systems. For example, each end user installs a new application on their machine, not expecting an application to mysteriously stop working. Most developers spend their time using Regedit, trying to keep all the necessary registration entries consistent in order to activate a COM class.

The design principles and implementation techniques used in the. NET Framework to resolve DLL Hell issues are based on the Microsoft windows®2000, and the end of DLL Hell (English) and David D ' S of Rick Anderson Ouza, BJ Whalen and Peter Wilson's implementing Side-by-side Component sharing in Applications (Expanded) (English) are described in.. NET Box Many of the features provided by the rack are described in both articles, including application isolation and parallel components for applications built on the. NET platform. You will learn about the version support that is available on the. NET platform, which brings together local Windows applications more closely.

This article describes the concept of a compilation and describes how. NET uses compilations to troubleshoot versioning and publishing issues. We will discuss in particular how the assembly is built, how it is named, and how compilers and the common language runtime use compilations to record and enforce version dependencies between application fragments. We will also discuss how applications and administrators can customize version behavior through what we call version policy.

After the assembly is introduced and illustrated, several publishing scenarios are presented to give you some idea of the various packaging and distribution options available in the. NET framework.


Problem description


From the customer's point of view, the most common version problem is what we call the DLL Hell problem. In short, DLL Hell refers to a series of problems that arise when multiple applications attempt to share a common component, such as a Dynamic Connection library (DLL) or a Component Object Model (COM) class. Most typically, an application will install a new version of the shared component that is not backward compatible with the existing version on the machine. Although the application you just installed is functioning correctly, an application that originally relied on the previous version of the shared component may no longer work. In some cases, the cause of the problem is more unpredictable. For example, when a user browses to some Web site, a Microsoft ActiveX® control is downloaded at the same time. If you download the control, it replaces any existing version of the control on the machine. If an application on the machine is using the control, it is likely that it will also stop working.

In many cases, it will take a long time for the user to discover that the application has stopped working. The result is often hard to remember when machine changes affected the application. The user may recall something that was installed a week ago, but the installation is not clearly associated with the state that is currently being seen. Worse still, there are few diagnostic tools available to help users (or help their technical support staff) determine what's wrong.

These problems are due to the fact that version information for different components of the application is not logged or enhanced by the system. Also, the changes that the system makes to an application affect all applications on the machine-now it is not easy to build an application that is completely isolated from change.

One reason for the difficulty of creating an isolated application is that the current run-time environment allows only individual versions of components or applications to be installed. This limitation means that the creator of the component must write their code in a backward-compatible manner, or else there is a risk of terminating an existing application when they install a new component. In fact, it's very difficult to write code that is always backwards compatible if possible. In. NET, the side by side concept is the core of the versioning problem. "Side by Side" is the ability to run different versions of the same component on the same machine at the same time. With support for parallel components, programmers do not have to work hard to maintain strict backward compatibility because different applications are free to use different versions of a shared component.

Publishing and installing

Installing the application now is a multi-step process. Generally, installing an application involves replicating many software components to disk, and a series of registry entries that describe those components in the system.

The separation of the keys in the registry and the file on the disk makes it very difficult to copy applications and uninstall them. Also, the relationship between many of the items required to fully describe a COM class in the registry is very loosely related. These items often include entries for union classes, interfaces, type libraries, and DCOM app IDs, and do not involve any items placed in the registry document extensions or component categories. Always keep these items synchronized manually.

Finally, the registration footprint is required to activate any COM class. This greatly complicates the process of publishing distributed applications because the appropriate registry entries must be made to each client's machine.

Another common problem now is that it is unrealistic to update a running application. This is the biggest problem with Web applications, and the Web application must stop working and restart to update the COM classes that the application uses.

These problems are mainly caused by component descriptions that are separated from the component itself. In other words, the application is not self-describing and independent.


Characteristics of the solution

The. NET framework must provide the following basic capabilities to solve the problem just described:

The application must be self-describing: The self-describing application removes dependency on the registry, enabling installation without impact and simple uninstall and replication.

Version information must be logged and enhanced: Version support must be built inside the platform to ensure that the appropriate version of the dependency is loaded at runtime.

You must remember the last known Good configuration: When the application runs successfully, the platform must provide the ability to remember the components that work together-including their versions.

Parallel components must be supported: allows multiple versions of components to be installed and run on the machine at the same time, allowing callers to specify the version they want to load instead of the unknowingly coerced version. The. NET framework allows a parallel neighbor to step forward by allowing multiple versions of the framework to exist simultaneously on a separate machine. This greatly simplifies the upgrade issue because administrators can choose to run different applications on different versions of the. NET Framework.

You must isolate the application: the. NET framework must simplify (and, in fact, default) write applications that are unaffected by changes in other applications on the machine.


Assembly: Building Blocks

A compilation is a building block used by the. NET framework to solve the version and issue of issues just described. A compilation is a publishing unit of types and resources. In many ways the assembly is the same as the current DLL. In essence, the assembly is a "logical DLL".

The assembly is self-describing from the metadata invocation manifest. Just as. NET uses metadata description types, it also uses metadata to describe the assembly of the containing type.

The assembly is not just about publishing. For example, the version in. NET is done at the assembly level-without any reduction, like a version of a module or type. Also, compilations are used to share code between applications. A assembly that contains a type is part of the type's flag.

The code that accesses the security system uses the assembly in the kernel of its licensing model. The author of the Assembly records a set of licenses that are required to run the code in the list, and the administrator authorizes the license to the assembly based code, which contains the code.

Finally, the Assembly is also the core of the type system and the Run-time system, in which they establish a visual boundary for the type and service as the running time range of the resolution reference type.

Compilation list

The list clearly includes the following relevant compilation data:

Identification: A compilation identity consists of three parts: name, version number, and option culture.

File list: The list includes a list of all the files that make up the assembly. For each file, the encryption information for its name and content is recorded when the manifest is created. This information is validated at run time to ensure consistency of the publishing unit.

Citation compilation: The relationship between the compilations is kept in the collection of compiled lists. Dependent information includes the version number, which is used to ensure that the correct version of the relationship is loaded at run time.

Output types and resources: visual options available for types and resources include "visual only in my assembly" and "visible to callers outside my assembly." ”

Licensing Requirements: Assembly licensing requirements are grouped into three groups: assembly run requirements, required but there are also some requirements for the Assembly, even unauthorized functionality, and the author does not want to compile the mandated requirements.
The IL disassembly (Ildasm) SDK tool is useful for viewing code and metadata in the assembly. Figure 1 is a list of examples with Ildasm reality. Assembly represents the compilation and. assembly extern contains information about other compilations.

Figure 1. List of examples shown in IL disassembly

Assembly structure

So far, the compilation is mainly described in terms of logical concepts. This section describes how they are physically embodied to help you make the assembly more specific.

Typically, the assembly consists of four elements: an assembly metadata (a manifest), a metadata description type, a media language (IL) code that implements that type, and a set of resources. Not all of these are present in each assembly. Only the checklist is strictly required, but the type or resource needs to be compiled with some important features.

There are several options for how these four elements can be packaged. For example, figure 2 represents the entire assembly: manifest, type metadata, IL code, and resources.

Figure 2. DLLs that contain all assembly elements

In another case, the content of one assembly may be split into multiple files. In Figure 3, the author chooses to detach some useful code into a different DLL and keep a large resource file in its original file (here is a JPEG file). One reason to do this is to optimize the download of the code. The. NET Framework downloads files only when they are referenced, so if the assembly contains code or resources that are frequently accessed, separating them into separate files will increase the efficiency of the download.

Figure 3. Assembly elements split into multiple files


Versions and shares

DLL Hell A primary purpose is to share models that are currently used in component-based systems. By default, separate software components are shared by multiple applications on the machine. For example, each time an installer replicates a DLL to the system directory or registers a class in the COM registry, the code potentially affects other applications running on the machine. In fact, if an existing application uses the previous version of the shared component, the application will automatically use the new version. This is certainly better if the shared component is strictly backward-compatible, but it is difficult to maintain backward compatibility in many cases if it is not possible. If backward compatibility is not maintained or cannot be maintained, the side effects that are installed as other applications often cause application outages.

One of the principles of the. NET design policy is to isolate components (or assemblies). Isolating a compilation means that a compilation can only be accessed by one application-not shared by multiple applications on the machine and not likely to be affected by changes to the system by other applications. Isolation gives developers absolute control over the code used by the application. Isolation, or an application-specific assembly is expected to be default in. NET applications. The trend of isolating components has started with the introduction of. local files in Microsoft Windows 2000. This file is used to make the OS Loader and COM first lookup from the application directory when trying to locate the required components. (Refer to the documentation in the MSDN Library, implementing side-by-side Component sharing in applications.) )

In some cases, however, it is necessary to share the assembly between applications. It is obvious that each application has its own copy of the system.winforms, system.asp, or public Web table control that is meaningless.

In. NET, it is a clear decision to share code between applications. Sharing a compilation requires some additional requirements. In particular, the shared assembler should support the same assembly side by version with multiple versions installed and running on the same machine, or even in the same process, at the same time. In addition, shared compilations have more stringent naming requirements. For example, a shared assembly must have a globally unique name.

The need for isolation and sharing leads us to consider two kinds of compilations. This is a fairly loose set, and there is no real structure between the two, but how they are used is different: dedicated to an application or shared with many applications.

Application-specific assembly

An application-specific assembly is a visual assembly that is visible only to an application. We expect this to be the most common scenario for. NET applications, because the. NET Framework helps build applications that are isolated from system changes caused by other applications.

The naming requirements for a private assembly are simple: The assembly name must be unique within the application. It is not necessary to have a globally unique name. Keeping names is not a problem because application developers have complete control over which assembly is isolated from the application.

Application-specific assemblies are deployed in the application directory structure where they are used. A private assembly can be placed directly in the application's directory or in its subdirectories. The common language runtime finds these compilations through a process called probing. "Probing" is a simple mapping between the assembly name and the file name that contains the manifest.

In particular, the universal language runtime records the name of the assembly in the assembly reference, appends ". dll" and looks up the file in the application's directory. There are variables in the scenario where the runtime accesses the compiled named subdirectory or the assembly-styled subdirectory. For example, a developer would choose to deploy a compilation of resources that contains a location in Germany to a subdirectory called "de" and deploy Spanish resources in a subdirectory called "es".

As mentioned earlier, each compilation list includes information about the version of its relationship. This version of the information is not enhanced for private compilation because the developer has complete control over the assembly deployed to the application directory.

Shared assembly

The. NET Framework also supports the concept of shared compilations. A shared assembly is used by multiple applications on a machine. Using. NET, sharing the code between applications is a clear decision. The shared assembly has some additional requirements for solving the shared problems we are experiencing now. In addition to supporting the juxtaposition previously described, there are many strict naming requirements for shared assemblies. For example, a shared assembly must have a globally unique name. And the system must provide "name protection"-more specifically, to prevent someone from using the writer's assembler name again. For example, suppose you are a manufacturer of a grid control and have published your assembly version 1. For writing you need to be sure that no one else can post a compilation or your grid control that claims to be version 2. The. NET Framework supports these naming requirements through technical support called share names. (Detailed in the next section).

In general, application writers do not have the same level of control over shared compilations used by applications. As a result, version information is checked each time the shared assembly is referenced. In addition, the. NET framework allows applications and administrators to overload the shared assembly version that applications use by specifying version policy.

Shared compilations are typically deployed to the Global Assembly library. A global assembler is a machine-wide assembly library for use by multiple applications. Using this library is not a requirement, but there are many advantages to doing so. For example, multiple versions of assembly-side storage are automatically provided. Also, administrators can use the library to deploy defect fixes or security patches that are used by applications on every machine they need. In this scenario, the configuration assembly to the global assembler storage can affect multiple applications on the machine. The. NET framework uses the concept of version policy (described later) to resolve issues that now appear in the shared area of the system, such as%windir%\system32.

Adding a compilation to a library requires explicit administrator action-in fact, the installation process must have administrator permissions. The assembly never ends at the end of the store as a side effect of running an application, nor is it any storage for a shared assembly that is currently working. In the Visual Studo. NET time frame, Windows installer will be updated to understand the assembly and assembly library. This means that you can use all of the features of Windows installer, such as selecting installation and application recovery using. NET applications.

The. NET SDK includes two tools for assembling libraries. The first is a tool called AL, which allows you to add compilations to the library. AL makes development and test scenarios easier, without creating an entire Windows installer package to add a compilation to the library. To add a compilation to a library using the/install switch:

The second tool is the Windows Shell Extension, which allows you to use the Windows Explorer Operations Library. Figure 4 Represents a view of the global Assembler library.

Figure 4. Global Assembly Library

Share name

The share name is used to combine strict naming requirements with shared assemblies. Share names have three goals:

Name unique: The shared assembly must have a globally unique name.

Prevent name impersonation: As a developer, you do not want someone to publish a successor to your compilation and falsely call it your release, whether accidental or intentional.

Provides a reference identifier: When it comes to referencing a compilation, the share name is used to ensure that the loaded assembly comes from the desired publisher.
The share name is implemented using public key encryption. Typically, the procedure looks like this: the writer of the Assembly produces a pair of keys (or uses it already), marks the file containing the proprietary key list, and provides the caller with a public key. When the assembly is referenced, the caller records the public key corresponding to the strong-name proprietary key. Figure 5 briefly describes how the process works during development, including how the key is stored in the metadata and how the signature is generated.

The program is called the "Main" assembly, which refers to a compilation called "Mylib". Mylib has a share name. The important steps are described below.

Figure 5. The process of implementing a share name

The developer invokes the compiler that is passed in the key pair and a set of source files for the assembly. Key pairs are typically generated by the SDK tool called SN. For example, the following command generates a new key pair and saves the file:
Sn 杒 mykey.snk
Most compilers will assemble as part of the edit step. The following is an example of a C # command that accepts a key pair and signs the assembly:

Csc/t:library math.cs/a.keyfile:mykey.snk/a.version:
When the compiler generates the assembly, the public key is kept in the manifest as part of the assembly identity. Includes a public key as part of the identity to provide a globally unique name to the assembly.

After the assembly is generated, the file containing the manifest is marked by a proprietary key. The resulting signature is saved in the file.

When the compiler generates the main assembly, the public key of the Mylib assembly is stored in the main manifest as part of the reference mylib.
At run time, there are two steps in the. NET framework to ensure that share names give developers the benefits they need. First, verify the Mylib share name signature when the assembly is installed to the Global Assembly library. (the option to verify the signature that is not configured to the library is also available.) Verify that the signature guarantees that the contents of the Mylib have not changed since the Assembly was established. The second step is to verify that the public key saved as part of the Main reference mylib matches a public key that is part of the Mylib identity. If these keys are the same, the author of main will be able to ensure that the Mylib version that is loaded comes from the same publisher who wrote the Mylib version of Main. When the Main reference Mylib is involved, the key equivalence check completes at run time.

The term "signature" is often associated with a Microsoft Authenticode. It is important to understand that there is no relationship between the share name and the Authenticode. The two technologies have different goals. In fact, Authenticode means a level of trust to the publisher, and the share name is not. There is no authorization license or Third-party signing authorization associated with a strong name. In addition, the share name signature is usually performed by the compiler itself as part of the compilation process. However, there are also utilities for signing in the SDK.

Another worthy consideration is the "Test signature" project. Compilers often fail to access proprietary keys that require full signing. Most companies are very good at protecting the storage of these keys and it can only be accessed by a few people. As a result, the. NET Framework provides a small amount of "test signature" technology in development and then "real signature."


Version Policy

As just described, each assembler list records the version information that it creates for each relationship it relies on. However, there are some scenarios where the creator or administrator of the application needs to run at run time with different versions of the relationship. For example, an administrator should be able to publish a troubleshooting version without recompiling each application to get the modification. Also, an administrator must be able to list a detailed version of the assembly that was not used because of a security breach or service failure. The. NET framework enables this flexibility in version binding through version policy.

Assembly version Number

Each assembly has a four-part version number as part of its identity (that is, some compilations of version and version are completely different from the class loader-related identities). The version included as part of the identity is primarily used to distinguish the version of the assembly for parallel purposes.

Developers and administrators must understand the structure of the version number because it is the key to how the common language runtime strengthens the version relationship between compilations.

Figure 6. Four parts of the assembly version number

Several parts of the version number are major, minor, build, and revision. Changes in major or minor versions can be considered incompatible. For example, developers have changed the type of some method parameters or removed some of the types altogether. The class loader uses this information to make incompatible versions of the dependent assembly not loaded by default.

On the other hand, changing only the build and version parts of the version number can be considered compatible. These changes are generally troubleshooting or security patches, in which case the type definition does not somehow interrupt the caller's change, which is compatible. These compatible changes are often referred to as Quick fix Engineering (QFE) fixes or dynamic fixes.

The default version policy

When a common language runtime encounters a reference to a compilation in code, it decides to load the version of the dependent assembly. By default, the assembly that loads the resolution reference must have the same major and minor version number as the record in the reference. If these numbers are different, the compilation is considered incompatible and will not be loaded by default. Instead, the universal language runtime is QFE (or dynamically repaired) with the highest number.

For example, if Main is compiled in Mylib version, when the Version of Mylib is found, the is loaded.

A policy that always takes the latest compilation and version is called an automatic QFE policy. The primary purpose of this principle is to allow administrators to publish the troubleshooting version without recreating all applications.

Customizing version Policy

Sometimes the default policy described earlier is not what you want. For example, perhaps an application is inadvertently interrupted by an installed QFE.

The default version policy can be modified by using an XML configuration file. With respect to the version, there are two files: An application description file and a machine scope or administrator file. The application description file is saved in the same directory as the application. The policy description in this file affects only the application. Machine-wide policy files are currently saved in the Windows directory. This file is used by the administrator to describe policies that affect all applications on this machine. For example, perhaps an administrator identified a detailed version of a compilation with some security vulnerabilities, and he ensured that the Assembly would no longer be used.

Examples of custom policies include:

Binding the specified version

Sometimes it is necessary to bind a compilation that is completely different from the version of the manifest record. Provide support for the program through the <BindingPolicy> tags in the configuration file. This policy is used to map a reference to a relationship-specific version or to all versions of a relationship.

The following example maps a reference to a version of Assembly called CALCR:

<bindingredir name= "CALCR"
Originator= "32AB4BA45E0A69A1"
version= "*" versionnew= ""
uselatestbuildrevision= "Yes"/>

Turn off automatic QFE policy

This policy allows you to stop the "automatic QFE Policy" reference to the assembly that has been provided. <BindingPolicy> tags are also used here, but the Uselatestbuildrevision property is set to No, as shown in the following example:

<bindingredir name= "CALCR"
Originator= "32AB4BA45E0A69A1"
version= "*" versionnew= "6.1.1212.14"
uselatestbuildrevision= "No"/>

Safe Mode

The Safe mode (or compile-run) policy is used to restore the compilation configuration. Enabling this policy enables the common language runtime to load an exact version of the relationship that is recorded in the manifest. Probably the application works when it is created, tested, and first published. Safe Mode is a network that is used to restore security to that state. The following XML code opens the Safe mode for a specific application:

<appbindingmode mode= "Safe"/>

If a specific relationship does not conform to the version rule or inadvertently introduces an error, the Safe mode and turn off automatic QFE principles can be used to restore the application to a work state.

Stages in a policy solution

This article has introduced several versions and publishing concepts, including application-specific compilations, shared compilations, global assembler storage, and XML files for the specified version policy. This section connects these concepts by describing the phases of common language runtime lookup compilation and application versioning strategies.

When the common language runtime encounters a reference to another assembly stored in the metadata, the process of loading the assembly begins. Depending on the reference, the following steps determine which version of the Assembly to load:

Refer to the application description file to see if the policy is specified. If it is, modify the original file with the policy information. For example, if you refer to the specified version and the application description policy file specifies the version, the common language runtime will be treated as if the initial specified version

Finds a matching assembly in the application directory (and subdirectories). "Match" is defined as an exact major and minor version number (unless the QFE policy is prohibited).

The Global Assembly library is referenced by QFE, regardless of whether a match is found by looking for it. This enables administrators to post troubleshooting that everyone should get.

Finally, refer to the Administrator policy file. The final reference to this file is because the administrator finally decided which version to load.



A publication contains at least two different aspects: packing code and distributing the wrappers to the client and server running the application. The main goal of the. NET Framework is to simplify the feasibility of publishing and replication publishing through a no-impact installation. The nature of assembly self-describing allows us to get rid of the registry dependency, making installation, uninstall, and replication quite simple. However, there are several situations where replication is not sufficient as a publishing mechanism. In these cases, the. NET Framework provides extended code download services and is integrated in Windows installer.


There are three packaging options available in the first version of the. NET Framework:

As-built (DLLs and EXE). On many occasions, special packaging is not required. The application is published in a format made by the publishing tool, a collection of DLLs and EXE.

Cab file. For more efficient downloading, Cab files can be used to compress applications.

Windows Installer package. Microsoft Visual Studio.NET and other installation tools allow you to establish a Windows installer package (. msi file). Windows Installer allows you to take advantage of application fixes, select installation, and other Microsoft Windows 2000 application management features.
Distribution Scheme

. NET applications can be published in a variety of ways, including replication, code downloads, and Windows installer.

For many applications, including Web applications and Web services, it is as easy to publish and copy a set of files to disk as to run them. Uninstalling and copying are as easy as deleting these files or copying them.

The. NET Framework provides support for downloading code using a Web browser. This section has several important issues, including:

0 Impact: No registry keys are added to the machine.

Incremental downloads: Many pieces of the assembly are downloaded only when they are referenced.

Download and application isolation: The download code that represents an application does not affect other applications on the machine. The main purpose of supporting code downloads is to prevent users from downloading a new version of a shared component that affects browsing specific WEB sites and affecting other applications.

No Authenticode dialog box: Code that accesses the security system is used to allow removable code to run in partial trust. The dialog box will no longer appear asking the user to choose whether to trust the code.
Finally,. NET is fully integrated into Windows Installer and Windows 2000 application management features.



The. NET framework can have 0 affected installation and access DLL Hell. A compilation is a self-describing, release unit that is used to enable these features.

The ability to create an isolated application is critical because it causes the application created to be unaffected by changes to the system by other applications. The. NET framework facilitates this application by publishing application-specific assemblies in the application's directory structure.

Parallelism is central to the issue of sharing and versioning in. NET. Parallel allows multiple versions of a compilation to be installed and run on the machine at the same time, and allows each application to request a specified version of that assembly.

The common language runtime records the version information between many applications and uses that information at run time to ensure that the appropriate version on which it relies is loaded. Application developers and administrators provide flexibility in selecting the loaded assembler version through version policy.

. NET provides several options for wrapping and publishing, including Windows installer, code downloads, and simple replication.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.