Simplify the release and solve the DLL HELL problem Steven Pratschner by using the .NET framework.
Microsoft Corporation
September 2000
Summary: This article introduces compilation concepts and explains how the .NET framework uses compilation solutions and release issues.
table of Contents
Introduction to the Characteristics of the Solutions: Building blocks version and shared version strategy release summary
Introduction
The Microsoft® .NET framework introduces several new features to simplify the application to publish and resolve DLL Hell. Both end users and developers are familiar with versions and release issues, which will accompany us today with component-based systems. For example, each end user has a new application on their machines, and it is not expected to stop working mysteriously. Most developers spend time using regedit, trying to keep all necessary registration entries to activate the COM class.
The design principles and implementation techniques for solving the DLL Hell problem in the .NET framework are based on the End of DLL Hell (English) and David D'Souza, BJ Whalen and David D'Souza, BJ Whalen and David D'Souza, BJ Whalen and David D'Souza, BJ Whalen and In the Implementing Side-by-Side Component Sharing in Applications (English) (English) of Peter Wilson. Many of the features provided by the .NET framework are described in these two articles, including application isolation and parallel components, used to build applications in the .NET platform. You will learn about the version support provided on the .NET platform, which makes the local Windows application more closely.
This article describes the concept of compilation and describes how .NET uses assembly to solve the version and publish issues. We will specialize how to build, how to name, and how to use assembly when compiler and generic language runtime, and enhance the version dependence between applications. We will also discuss how applications and administrators can customize version behavior through our own version strategy.
After introducing and explaining the compilation, several publishing programs will be displayed so that there are some understanding of the various packaged and distribution options provided in the .NET framework.
Problem narrative
version
From the perspective of the customer, the most common version is the problem that what we said is DLL Hell. Simply put, DLL Hell refers to a series of issues that are triggered when multiple applications try to share a public component (such as a dynamic connection library (DLL) or a component object model (COM) class). The most typical situation is that an application will install a new version of shared components, and the component is not compatible with the existing version on the machine. Although the just installed application is operating normally, the application that relies on the previous version of the shared component may have no longer work. In some cases, the cause of the problem is more difficult to expect. For example, download a Microsoft ActiveX® control at the same time when the user browses some Web sites. If you download the control, it will replace any of the original version of the control on the machine. If an application on the machine uses the control, it is likely to stop working.
In many cases, the user will take a long time to find that the application has stopped working. As a result, it is often difficult to remember when the machine changes affect the app. Users may recall some things a week ago, but there is no significant association with the status that is currently seen. Worse, there are now few problems that have a few diagnostic tools help users (or helped their technical support personnel).
The reason for these issues is that the version information of different components of the application is not recorded or strengthened by the system. Moreover, the changes made by the system will affect all applications on the machine - it is not easy to create applications that are completely isolated from changes.
It is difficult for a reason to establish an isolated application that the current runtime environment allows only separate version components or applications installation. This limitation means that the component's writer must write their code in a backwardly compatible manner, otherwise there will be the risk of termination of the application when they install new components. In fact, if possible, write the code that is always backward-compatible is very difficult. In .NET, the Side by Side concept is the core of the version problem. "Side by Side" is the ability to run different versions of the same components simultaneously on the same machine. Using components that support, 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 installation
The installation application is now a multi-step process. Typically, install an application includes copying a number of software components to disk, and a series of registration items describing those components in the system.
Items in the registry and the files on disk make replication applications and uninstall them very difficult. Moreover, the relationship between many items required for a COM class is fully described in the registry. These items often include items for joint classes, interfaces, type libraries, and DCOM App IDs that do not involve any items placed in registry document extensions or component categories. Hand manually maintain the synchronization of these items.
Finally, the registered footprint is required to activate any COM class. This greatly complex the process of publishing a distributed application because the appropriate registration item must be performed to each client.
Another common problem today is that updating a running application is unrealistic. This is the biggest problem with web applications. The web application must stop the work and then restart to update the COM class used by the application.
These problems are mainly caused by the components from the components. In other words, the application is not self-description and independent.
Solution features
The .NET framework must provide the following basic capabilities to resolve the problem just described:
The application must be self-description: The self-description application removes the dependence on the registry, can uninstall, and copies without an impact. Version information must be recorded and enhanced: Version Support must be built within the platform to ensure that the dependent's appropriate version is loaded at runtime. I must remember "The last known correct configuration": When the application is successful, the platform must provide the ability to remember the components of this set of work - including their version -. Squiring components must be supported: allowing multiple versions of components to be installed and running on the machine, allowing the caller to specify the version they need to load instead of unknowingly forced versions. The .NET Framework is one step by step by allowing the framework to simultaneously exist on a separate machine. This greatly simplifies the upgrade problem because the administrator needs to select different applications that run different versions .NET framework. The application must be isolated: .NET Framework must be simplified (actually default) Writing applications that are not affected by other applications on the machine.
Compilation: Building blocks
The assembly is a .NET framework for resolving the building blocks of the original version and the issuance issue. Compilation is the publishing unit of type and resource. In many aspects, compilation is the same as the current DLL. In essence, the assembly is "logical DLL".
The assembly is described in order through metadata calls. Just like .NET uses metadata description type, it also uses metadata descriptions that contain assembly.
Compilation is not only related to the release. For example, the version in .NET is completed in the assembly layer - there is no reduction, just like a module or type of version. Moreover, compilation is also used to share code between applications. A compilation containing a type is part of this type flag.
Access the code of the security system uses compilation in the kernel of its license model. Compilation writers record a group of licenses required to run the code in the list, and then the administrator licenses the license to the assembled code, and this assembly contains the code.
Finally, assembly is also the core of type system and runtime system, which has established a visual boundary as a type of runtime range for the type and service as a resolution type.
Assembly list
The list is clearly including the following compilation data:
Identification: A assembly identifier consists of three parts: name, version number, and option culture. File list: List includes all file lists that make up assembly. For each file, record the encryption information of its name and content when the list is created. This information is verified at runtime to ensure the consistency of the publishing unit. Quoted assembly: The relationship between assembly is saved in the collected compilation list. The dependent information includes the version number, which is used to ensure that the correct version is loaded. Output Types and Resources: Visual options available to types and resources include "visible only in my assembly" and "the caller to me outside of my assembly." License needs: Compilation license requirements are divided into three groups : Compilation of running demand, requires, but compilations, there are some needs of unauthorized features, as well as writers don't want to compile the authorized demand. IL disassembly (ILDASM) SDK Tool is helpful for viewing code and metadata in assembly. Figure 1 is a list of examples of ILDASM reality. .assembly indicates that the assembly .Assembly Extern contains information on other assembly.
Figure 1. Example list displayed in IL disassembly
Assemble structure
As soon as this, the assembly is mainly described in a logical concept. This section describes how they are physically reflected in the compilation more specific.
Typically, compilation consists of four elements: assembly metadata (list), metadata description type, realizing this type of media language (IL) code, and a set of resources. Not all of these appear in each assembly. Only the list is strictly needed, but type or resource needs to be compiled some important features.
There are several options on how these four elements can be packaged. For example, Figure 2 shows the entire assembly: list, type metadata, IL code, and resources.
Figure 2. DLL containing all assembly elements
Alternatively, a compilation content may be divided into multiple files. In Figure 3, the author chooses some useful code into a different DLL and retains a large resource file in its original file (here a JPEG file). One reason why this is to optimize the download. The .NET framework only downloads the file only during reference, so if the assembly contains code or resources that are frequently accessed, then divide them into separate files will increase the efficiency of downloading.
Figure 3. Assembly elements are divided into multiple files
Version and sharing
A main purpose of DLL Hell is to share the model used in component-based systems. By default, separate software components are shared by multiple applications on the machine. For example, each time a setup copys a DLL to the system directory or register a class in the COM registry, which potentially affects other applications that run 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. If the shared component is strictly compatible, it is of course better, but if it is impossible, it is difficult to maintain backward compatibility in many cases. If it is not maintained backward compatible or cannot maintain, the side impact as other application installations often causes the application to be interrupted.
One principle of the .NET design policy is to isolate components (or assembly). Isolation a compilation means that a compilation can only be accessed by an application - not shared by multiple applications on the machine and cannot be influenced by other applications. Isolation gives the developer absolute control to the code used by the application. Isolation, or application dedicated assembly is expected to be default in .NET applications. The Trend of Isolation Components In Microsoft Windows 2000, with the introduction of the .local file has begun. This file is used to try to locate the required components to find OS Loader and COM first look up from the application directory. (See related documents in MSDN Library, Implementing Side-by-Side Component Sharing In Applications.).
However, some cases are necessary to share assembly between applications. It is clear that each application has its own system.winforms, system.asp, or a copy of the public Web table control. In .NET, shared code between applications is a clear decision. Sharing assembly requires some additional needs. In particular, shared assembly should support the same compilation and multiple versions of multiple versions to install and run on the same machine, or even in the same process, in the same time. In addition, shared assembly has a more stringent naming needs. For example, a shared assembly must have a globally unique name.
Isolation and sharing needs to lead us to consider two compilation. This is a fairly loose collection, there is no practical structure between these two assembly, but how they are used different: dedicated to an application or share with many applications.
Application special assembly
Application dedicated assembly is a compilation that is only visible to an application. We expect this to be the most common situation of the .NET application, because .NET Framework helps establish an application that is isolated from other applications.
Named requirements for dedicated assembly is simple: assembly names must be unique in the application. There is no need to gain a global unique name. The only thing to keep the name is not a problem because application developers fully control which assembly is isolated from the application.
Application dedicated assembly deployment in the application directory structure. Dedicated assembly can be placed directly in the application's directory or in its subdirectory. General Language Runtime Find these compilation through a process called Probing. "Probing" is a simple mapping between the assembly name to the file name containing the list.
In particular, universal language runtime records the assembly name in the assembly reference, adding ".dll" and find the file in the application's directory. There are some variables in this scenario where runtime will access the subdirectory named in the subdirectory of the compilation name or assembly. For example, a developer chooses to deploy assembly containing resources to Germany in subdirectory called "DE", and deploy Spanish resources in subdirectory called "ES".
As mentioned earlier, each assembly list includes version information about its relationship. This version information is not strengthened for dedicated assembly, because developers fully controlled assembly to the application directory.
Share compilation
The .NET framework also supports the concept of shared assembly. Sharing assembly is used by multiple applications on the machine. Use the code between .NET and shared applications is a clear decision. Sharing assembly Some additional additional needs are used to solve the problem of sharing we have experienced. In addition to supporting parallel first, share compilation has many strict naming requirements. For example, shared assembly must have a globally unique name. Moreover, the system must provide "Name Protection" - more specifically, prevent someone to use the writer's assembly name. For example, suppose you are a manufacturer of a grid control, and publish your assembly version 1. As a written you need to be sure that no other person can publish a compilation or your grid control that claims to version 2. The .NET Framework supports these naming requirements through technical support known as shared names. (Detailed description in the next section).
Typically, the application writer does not have the same degree of equivalent control for shared assembly used by the application. As a result, the version information is checked at each reference sharing assembly. In addition, the .NET framework allows applications and administrators to overload the shared assembly version used by the specified version policy.
Sharing assembly is usually deployed to a global assembly. Global Assembly is an assembly library for machine ranges for multiple applications. It is not necessary to use the library, but there is a lot of benefits. For example, automatically provide multiple versions of compilation parallel storage. Moreover, administrators can use the library to deploy the defect fixes or security patches to use on each machine they need. In this scenario, configuration assembly to global assembly storage can affect multiple applications on the machine. The concept of .NET Framework Using Version Policies (later description) solves problems that are now shared in the system, such as% WINDIR% / System32.
Add assembly in the library requires a clear administrator to operate - in fact, the installation process must have "administrator privileges". Compilation never in the storage end as the side impact of running an application, nor is it any stored for shared assembly. In the Visual Studo .NET time frame, the Windows Installer will be updated to understand the compilation and assembly. This means that all features of the Windows installer can be used, such as using the .NET application to select installation and application recovery. .NET SDK includes two tools for assembly libraries. The first is a tool called Al, which allows assembly in the library. The AL makes the development and test scheme easy, it does not need to create a full Windows installer package to add a compilation in the library. Use / install switch to add assembly in the library:
Al /install:myassembly.dll
The second tool is Windows Shell Extension, which allows you to use the Windows Explorer to operate library. Figure 4 shows a view of a global assembly.
Figure 4. Global Assembly
Share name
A shared name is used to combine strict naming requirements with shared compilation. Shared names have three goals:
The name is unique: sharing assembly must have a global unique name. Prevent name prevention: as a developer, do not want someone to release your compiletable version and assume that it is issued, whether unexpected or deliberate. Provide a reference identifier: When a compilation is involved, a shared name is used to ensure that the assembly from the desired issuer.
The shared name is implemented using public key encryption. Typically, the process is as follows: The compilation writer generates a pair of keys (or uses existing), and the flag contains a file containing a 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 draws how the process works during development, including how the key is stored in metadata and how to generate a signature.
The solution is called "main" assembly, which references a compilation called "MYLIB". MyLIB has a shared name. The important steps are as follows.
Figure 5. Process for achieving shared names
Developers call the compiler pairs in the key pair and a set of assembly source files. The key is usually generated by an SDK tool called Sn. For example, the following command generates a new key pair and saved file: SN 杒 mykey.snk Most compilers will assemble as part of the editing step. Below is an example of a C # command, it accepts the key pair and gives a compilation signature: CSC / T: library math.cs /a.keyfile:key.snk /a.Version: 1.0.0.0 When the compiler generates compilation, public The key is saved as part of the assembly identifier in the list. A part of the public key is included to provide a global unique name to the assembly as part of the logo. After assembly generation, the file containing the list is marked by a proprietary key. The result sign is saved in the file. When the compiler generates the main assembly, the public key of the MYLIB assembled as part of the reference MYLIB is stored in the list of MAIN.
Two steps in the .NET framework guarantees the benefits they need to share developers. First, verify the shared name signature of MYLIB when assembled to the global assembly. (Options not configured to verify signatures in the library are also available.) Verify the signature guarantee that the content of MYLIB has not changed since the assembly is established. The second step is to verify that the public key saved as part of the MAIN reference MYLIB matches a common key of a part of myLIB identity. If these keys are the same, the author of Main ensures that the loaded MYLIB version comes from the same publisher, the publisher writes the MYLIB version that creates Main. This key equivalent check is completed at runtime when it is involved in MAIN.
The term "signature" is often associated with Microsoft Authenticode. It is very important to understand the shared name and Authenticode without any relationship. These two technologies have different goals. In fact, Authenticode means the level of trust of the issuer, and the shared name is not. There is no license or third party signature authorization associated with strong names. In addition, the shared name sign is usually performed by the compiler itself as part of the compilation process. However, there is also a utility to sign in the SDK. Another worth considering the "test signature" project. Compilation writers often cannot access a proprietary key that needs to be fully signed. Most companies protect these keys for these keys. It can only be accessed by a few people. As a result, the .NET framework provides a small amount of "test signature" technology in the development, then "real signature".
Version strategy
If you have just described, each assembly list records the version information of each of the relationships that it depends on. However, there are some options for the application's writers or administrators to run with different versions of the relationship at runtime. For example, an administrator should be able to release a fault elimination version without re-compiling each application to get the modification. Moreover, the administrator must be able to list the detailed versions of the compilation of the discovery security vulnerability or service failure. This flexibility is enabled in the version binding through version strategy.
Compilation version number
Each assembly has four partial version numbers as part of it identifies (that is, some compilation version 1.0.0.0 and version 2.1.0.2 are completely different with the identification associated with the class loader). The version including a part of the identification is primarily used to distinguish the assembly of the parallelism.
Developers and administrators must understand the structure of the version number because it is the key to how to strengthen the version relationship between assembly time.
Figure 6. Four parts of the assembly version number
Several parts of the version number are major versions, secondary versions, internal versions, and revisions. The change in major versions or secondary versions can be considered an incompatible change. For example, developers have changed some types of method parameters or completely deleted some types. The type of loader uses this information to make the incompatible version of the compilation that the compilation is not loaded.
On the other hand, only the establishment and version sections in the version number can be changed to be compatible. These changes are generally troubleshooting or security patches, in which case the type definition is not changed to some extent, which is compatible. These compatible changes are often referred to as Quick Fix Engineering (QFE) fixes or dynamic fixes.
Default version strategy
When a generic language runtime encounters a compilation in the code, it decides to load the version of the compilation that is dependent. By default, the assembly of the load resolved reference must have the same main version number and the secondary version number as the record in the reference. If these numbers are different, the compilation is considered to be incompatible and will not be loaded by default. Instead, generic language runtime uses the highest number to get QFE (or dynamic fix).
For example, if MAIN is compiled in a version 1.0.0.0 version of MyLib, it will be loaded with 1.0.1.1 when the version 1.0.1.1 version of MYLIB is discovered.
Always take the latest compilation and version of the strategy called "Automatic QFE Policy". The main purpose of this principle is to allow administrators to release troubleshooting versions without recreate all applications.
Custom version strategy
Sometimes the default strategy described earlier is not what you want. For example, perhaps the application is uninterrupted by the installed QFE.
The default version policy can be modified by using an XML configuration file. About the version, there are two files: an application documentation and a machine range or administrator file. The application documentation is saved in the same directory as the application. The policy description in this document only affects the application. Machine Range Policy files are currently saved in the Windows directory. This file is used by administrators to describe policies that affect all applications on this machine. For example, perhaps an administrator determines that a detailed version of a compilation has some security vulnerabilities, and he makes sure the assembly will no longer be used.
Examples of custom strategies include:
Bind the specified version
Sometimes you need to bind a completely different compilation with the list of records recorded. Support for this scenario by providing the
Originator = "32AB4BA45E0A69A1" Version = "*" VersionNew = "6.0.0.0" UseLatestBuildRevision = "yes" /> Bindingpolicy> Turn off automatic QFE strategy The policy allows the "Automatic QFE Policy" to be stopped. Originator = "32AB4BA45E0A69A1" Version = "*" VersionNew = "6.1.1212.14" UseLatestBuildrevision = "no" /> Bindingpolicy> Security mode Safety mode (or compiled) policy is used to restore compilation configurations. Enabling this policy will enable the general language runtime to load a precise version of the relationship recorded in the list. The approximate application works when it is created, tested and first published. Security mode is a network for restoring to this state. The following XML code opens security mode for specific applications: Bindingmode> If a specific relationship does not match the version rule or injects an error, "Security Mode" and "Off Auto QFE Principles" can be used to restore the application to a certain work. Stage during the policy solution This article has introduced several versions and published concepts, including application-specific assembly, shared assembly, global assembly storage, and XML files for specifying version strategies. This section connects these concepts by describing the general language runtime lookup assembly and application versions. When a universal language runtime encounters another assembly stored in the metadata, the assembly process is started. According to the reference, the following steps determine which version of the assembly: Reference application Description File View Whether the policy is specified. If so, modify the original file with the policy information. For example, if the specified version 1.0.0.0 is referenced, the application description policy file specifies version 2.0.0.0, the general language runtime will be processed as in the initial specified version 2.0.0.0. Find the matching assembly in the application directory (and subdirectory). "Match" is defined as an accurate main version number and the secondary version number (unless the QFE policy is disabled). Regardless of whether you find a match, the global assembly will be referenced by the QFE reference. This allows administrators to release the troubleshooting that everyone should get. Finally, refer to the administrator policy file. Last reference is given because the administrator finally decides which version is loaded. release The release contains at least two different aspects: packaging code and distributing these packages to clients and servers running the application. The main goal of the .NET framework is to simplify the feasibility of publishing and replication publishing through unaffected installation. The nature of the compiler is made to get rid of the dependence on the registry, so make the installation, unloading, and replication are quite simple. However, there are several applications that are replicated as the publishing mechanism is not sufficient. In these cases, the .NET framework provides an extension code download service and integrates in a Windows installer. package There are three packaging options available in the first version of the .NET framework: As-Built (DLL, and EXE). In many occasions, special packaging is not required. The application is published in format manufacturing, namely DLL and EXE. CAB file. For more efficient download, the CAB file can be used to compress the application. Windows installation package. Microsoft Visual Studio.net and other installation tools allow the Windows installation package (.msi file). The Windows Installer allows for application repair, selecting installation, and other Microsoft Windows 2000 application management functions. Distribution plan .NET applications can be released in a variety of ways, including copying, code downloads, and via Windows installer. For many applications, including web applications and web services, publish and copy a set of files to disk and run as simple as running. Uninstalling and replication is as easy as those of deleting these files or copy them. The .NET framework provides support for downloading code using a web browser. There are several important issues in this section, including: Zero impact: No registry key is added to the machine. Incremental download: Many of the pieces of assembly are only downloaded when referenced. Download and Application Isolation: Downloading code on behalf of an application does not affect other applications on the machine. The main purpose of supporting code download is to prevent users from downloading a new version of a shared component effect browsing the specific Web site and affecting other applications. No Authenticode dialog: Access the code of the security system is used to allow the mobile code to operate in partial trust. The dialog box will not appear to ask the user to choose whether to trust the code. Finally, .NET is fully integrated into the Windows installer and Windows 2000 application management feature. Summary The .NET framework is able to install and access the DLL Hell. The assembly is an self-description used to enable these features, version publishing units. The ability to create an isolated application is critical because it makes the created application not affected by other applications. The .NET framework promotes this application by publishing application-specific assembly in the application's directory structure. Parallel is the core of share and version of the problem. Parallel allows multiple versions of a compilation to install and run on the machine, and allow each application to request the specified version of the assembly. General Language Runtime Records the version information between many applications and uses this information when running, ensures that the appropriate version is loaded. Application developers and administrators provide flexibility in selection of subsequent assembly versions through version policies. .NET provides several packaging and published options, including Windows installer, code download, and simple replication.