Net Frame Work
Net Frame Work
Application domain is a construct in the CLR that is the unit of isolation for an application. The
isolation guarantees the following:
An application domain is lighter than a process. Application domains are appropriate for scenarios
that require isolation without the heavy cost associated with running an application within a
process. A process runs exactly one application. In contrast, the CLR allows multiple applications
to be run in a single process by loading them into separate application domains. Additionally, the
CLR verifies that user code in an application domain is type safe.
The Windows operating system does not provide support for running a CLR application. That
support is provided by a CLR host. A CLR host is an application that is responsible for loading the
CLR into a process, creating application domains within the process, and executing user code
within the application domains. Examples of hosts that ship with the .NET Framework include:
ASP.NET. An ISAPI filter that ships with ASP.NET loads the CLR and does the initialization
necessary to handle web requests.
Internet Explorer. A MIME filter hooks into Internet Explorer versions 5.01 and higher to
execute managed controls referenced from HTML pages.
Shell Executables. When a managed application is launched from a shell, a small piece of
unmanaged code loads the CLR and transitions control of the application to the CLR.
For more information see Hosting the Common Language Runtime.
The default domain is an application domain that is created automatically by the CLR every time it
is initialized in a process. The default domain is not unloaded until the process shuts down. Most
hosts dont run code in the default domain for two main reasons. First, the default domain cannot
be shut down independently of the process. Second, for security and isolation reasons, it is
desirable that the user code and hosting code execute in different application domains. Instead,
hosts create application domains with a set of properties that control security, isolation, loading,
etc.
What is an assembly?
An assembly is a reusable, versionable, self-describing deployment unit for types and resources it
is the primary building block of a .NET application. Assemblies provide the infrastructure to allow
the runtime to fully understand the contents of an application and to enforce the versioning and
dependency rules defined by the application.
The sets of types and resources that form some logical unit of functionality.
A manifest which is the metadata that describes how the types and resources relate and
what they depend on to work properly.
The first step in running managed code in a process is to get the CLR loaded and initialized using
a CLR host. Typically, a host consists of both managed code and unmanaged code. The
managed code which executes in the default domain is usually responsible for creating the
application domains in which the user code exists. All CLR hosts must contain unmanaged code
because execution must begin in unmanaged code. The .NET Frameworks provides a set of
unmanaged APIs that the host can use to configure the CLR, load the CLR into a process, load
the hosts managed code into the default domain, and transition from the unmanaged code to the
managed code.
The second step in running managed code in a process is to create application domains in which
the user code will execute. The creator of the application domain can specify criteria which
control code isolation, security, and loading of assemblies.
The third step in running managed code in a process is to execute user code in one or more
application domains created in the previous step. All code that is run in the CLR must be part of
an assembly. There are three options for loading assemblies. First, precompiled assemblies can
be loaded from disk. Second, precompiled assemblies can be loaded from an array of bytes.
Third, assemblies can be built dynamically in an application domain using the BCL Reflection
Emit APIs.
Note. For an application launched from the command-line, the shell host executes the steps
described above on behalf of the user and hides the complexity from the user.
The System._AppDomain interface is meant for use by unmanaged code that needs access to
the members of the managed System.AppDomain class. Unmanaged code calls the methods of
the System._AppDomain interface through COM Interop. Unmanaged code can obtain a pointer
to the _AppDomain interface by calling QueryInterface on the default domain. See Hosting the
Common Language Runtime and Common Language Runtime Hosting Interfaces for details.
The default domain is created automatically when a CLR hosts unmanaged code calls the CLR
hosting interface to load the CLR.
A user application domain is created by calling one of the following overloaded static methods of
the System.AppDomain class:
Overload 1 allows an application domain to be created given its name. Overloads 2-3 allow a
System.Security.Policy.Evidence object to be supplied to CreateDomain to define the security
policy for the application. Overload 3 allows a System.AppDomainSetup object to be supplied to
CreateDomain to configure how assemblies are loaded into the application domain. Overload 4
allows some of the common configuration settings to be specified as parameters without defining
a System.AppDomainSetup object.
The AppDomainSetup class provides a set of properties that can be set or retrieved. The
properties control how assemblies are loaded into an application domain. The most important
properties are ApplicationBase and ConfigurationFile. The other properties are used mainly by
a CLR host and are described in the BCL documentation. A newly created application domain
inherits the ApplicationBase property of its creator. No other property is inherited by the new
application domain.
The ApplicationBase property defines the root directory for an application. When an assembly
needs to be loaded from the disk, the CLR will begin probing for the assembly in the directory
specified by the ApplicationBase property. This provides a degree of isolation in that the
assemblies that are loaded are privatized to a particular application.
The ConfigurationFile property defines the XML file that contains the configuration settings for the
application that executes in the application domain. The configuration file describes information
such as versioning rules and policies for locating types. For more information see Configuration
Files for the CLR.
The following code snippet creates an application domain with default security policy and specific
ApplicationBase and ConfigurationFile properties:
// C# Sample Code
using System;
The runtime enforces code-access security. In code-access security, what code is allowed to do is
based on the characteristics of the code called Evidence. The runtime maps the evidence to a
set of permissions when the code is loaded and run. The permissions control specific actions of
the code.
First, the host can provide evidence to an application domain when it is created by supplying an
Evidence object to System.AppDomain.CreateDomain. This supplied evidence is added to the
evidence for the code before the security policy for the code is evaluated. For example, the
following code snippet restricts code running in an application domain associated with a Web site
to no more permissions than code originating from the site:
// C# Sample Code
using System;
using System.Security.Policy;
Evidence.AddHost(new URL(http:://www.site.com);
Second, the host can restrict the permissions granted at a specific policy level. The hierarchy of
policy levels beginning at the top level are: enterprise wide policy, machine wide policy, per user
policy, and application domain level policy. Each policy level can restrict the permissions granted
by the level above it. The System.AppDomain.SetAppDomainPolicy is used to specify security
policy. For more information and an example of how to use the method, see Hosting the Common
Language Runtime.
The System.AppDomain class provides the following methods that can be used to run an
assembly in an application domain:
1. public int ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
Overload 1 is the most general form of ExecuteAssembly. The first parameter is the path name of
the assembly to be executed. The second parameter allows the caller to supply a
System.Security.Policy.Evidence object for the assembly. The last parameter allows the caller
to supply an array of parameters to be passed to main entry point of the assembly.
The steps necessary to execute an assembly in a remote application domain are as follows:
o Evidence to control specific actions of the code executed in the application domain.
Note that the ExecuteAssembly method will not work with executables generated by Visual C++
compiler due to the way the unmanaged CRT startup works.
The following code snippet shows how to execute an assembly named HelloWorld1:
// C# Sample Code
// File: ExecAssembly.cs
using System;
using System.Reflection;
using System.Runtime.Remoting;
public class ExecAssembly
dom.ExecuteAssembly("HelloWorld1.exe");
AppDomain.Unload(dom);
// C# Sample Code
// File: HelloWorld1.cs
using System;
using System.Threading;
Console.WriteLine(greeting);
o.SayHello("Hello World!");
csc ExecAssembly.cs
csc HelloWorld1.cs
The steps necessary to invoke a method in a remote application domain are as follows:
o Evidence to control specific actions of the code executed in the application domain.
Ensure the type containing the method to be invoked derives from
System.MarshalByRefObject. This is necessary to ensure that the type is marshaled by reference
across the boundary of the created application domain.
Unwrap the ObjectHandle to obtain an Object reference to invoke methods on the type.
The System.AppDomain class provides the following methods for instantiating a type:
The System.AppDomain class also provides the following convenience methods that combine the
operations of instantiating a type and unwrapping the ObjectHandle:
The following code snippet shows how to invoke the SayHello method in the HelloWorld2
assembly:
// C# Sample Code
// File: Invoke.cs
using System;
using System.Reflection;
using System.Runtime.Remoting;
// HelloWorld
if (objh == null) {
Console.WriteLine("CreateInstance failed");
return;
HelloWorld h = (HelloWorld)obj;
h.SayHello();
AppDomain.Unload(dom);
}
// C# Sample Code
// File: HelloWorld2.cs
using System;
using System.Threading;
if (greeting == null) {
_greeting = greeting;
Console.WriteLine(_greeting);
}
Note. The HelloWorld2 assembly must be locatable in the callers application domain and the
remote application domain. The assembly is loaded into the remote application domain by
CreateInstance. It is loaded into the callers application domain when the Object obj is cast to the
HelloWorld type.
Note. If the metadata for the invoked method SayHello is not available in the callers application
domain, you may get errors during JIT compilation.
An attempt to call AppDomain.Load on an application domain that is not the current application
domain will result in a successful load of the assembly in the target application domain. Since
Assembly objects are not MarshalByRef, when the method attempts to return the Assembly
object for the loaded assembly to the current application domain (i.e., the callers application
domain), the runtime will try to load the specified assembly into the current application domain.
The load may fail if the configuration settings (such as AppDomainSetup.ApplicationBase) for the
two application domains are different. Even when the loading into the current application domain
succeeds, the Assembly object that is loaded into the current application domain is different from
the assembly that was loaded into the target application domain.
The System.AppDomain provides the following methods for loading an assembly into an
application domain:
Note. Overloads 3 and 9 are obsolete and will be removed in a future release.
com.microsoft.crypto, Culture=
A fully specified reference for strong named assembly with culture en:
Partially specified AssemblyName which may be satisfied by either strong or simply named
assembly:
com.microsoft.crypto
com.microsoft.crypto, Culture=""
com.microsoft.crypto, Culture=en
The System.Reflection.Assembly class provides the following static methods for loading an
assembly into the current application domain:
1. public static Assembly Load(AssemblyName assemblyRef)
Note. Overloads 3 and 9 are obsolete and will be removed in a future release. Overload 1-9 of
Assembly.Load are similar to the overloads 1-9 of AppDomain.Load with the difference that the
static Assembly.Load methods load the specified assembly into the current application domain
while the instance AppDomain.Load methods load the specified assembly into the target
application domain. The same restriction on the assemblyName parameter that applied to
AppDomain.Load also applies to overloads 7-9, i.e., the assembly name should not be a path
name or a file name of the requested assembly and should not contain an extension such as .DLL
or .EXE in the name. Overloads 10-11 can be used to load an assembly from a specific location
by specifying a file name or path to the assembly.
Note. To ensure that assemblies loaded using Assembly.LoadFrom do not interfere with direct
dependencies of the managed application (obtained using Assembly.Load), the assembly cache
manager maintains separate load contexts, namely, a default load context and a LoadFrom
load context. The default load context records the assembly name and assembly instance
information of the transitive closure of dependent assembies that are directly used by the
managed application. The LoadFrom load context contains the assembly name and assembly
instance information for all assemblies loaded using Assembly.LoadFrom as well as the transitive
closure of their dependencies. For more information about load contexts, consult the SDK
documentation.
Note. The System.AppDomain class does not provide LoadFrom methods similar to the
System.Assembly.LoadFrom methods. If you wish to load an assembly into a target application
domain given a file name fro an assembly, you will need to use the following workaround:
Create a stub assembly that calls System.Assembly.LoadFrom using the file name of the
assembly to be loaded into the target application domain.
The assembly resolution is controlled by the configuration properties for the application domain
such as System.AppDomainSetup.ApplicationBase. The configuration properties may not be
sufficient in some hosting scenarios, especially if the host is creating assemblies in memory on
the fly using Reflection Emit, since there may not be an assembly on disk to find. In such cases,
you can use the System.AssemblyResolve event to hook into the type loading process.
The args parameter to ResolveEventHandler is the identity of the assembly the runtime is
seeking. The receipient of the event is free to resolve the reference to the assembly by any
means. For example, the receipient may construct an assembly on the fly, find it in a custom
location on disk, etc. The only requirement is that the receipient return a instance of
System.Reflection.Assembly.
The following sample code shows how to define a handler to resolve an assembly dynamically:
// C# Sample Code
// File AssemblyResolve.cs
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Remoting;
using System.Threading;
dom.AssemblyResolve += hndlr;
if (asm == null) {
Console.WriteLine("Main: Can't load assembly HelloWorld");
return;
Type t = asm.GetType("HelloWorld");
if (t == null) {
return;
{
// Write message that we are in the assembly resolver
asmName.Name = "DynamicHelloWorld";
ILGenerator il = meth.GetILGenerator();
il.EmitWriteLine("Hello World!");
il.Emit(OpCodes.Ret);
typ.CreateType();
Console.WriteLine("Returning dynamic assembly");
return asm;
csc AssemblyResolve.cs
A type is resolved dynamically by defining a handler for the TypeResolve event. The
TypeResolve event is defined as follows:
A resource is resolved dynamically by defining a handler for the ResourceResolve event. The
ResourceResolve event is defined as follows:
For both types and resources, the handler must resolve the assembly in which the entity is
defined. The code for the handler is very similar to the handler shown in the sample above.
CLR does not provide a way to unload an assembly. The only mechanism to remove the
assembly is to unload the application domain in which the assembly is loaded. If you wish to
remove an assembly after it has been used, you should create an application domain, load the
assembly into the created application domain, and then unload the application domain when you
no longer need the assembly.
You should use the following static method in the System.AppDomain class:
The Unload method gracefully shuts down the specified application domain. During shutdown no
new threads are allowed to enter the application domain and all application domain specific data
structures are freed. You cannot unload an application domain in a finalizer or destructor.
If the application domain has run code from a domain-neutral assembly, the domains copy of the
statics and related CLR data structures are freed, but the code for the domain-neutral assembly
remains until the process is shutdown. There is no mechanism to fully unload a domain-neutral
assembly other than shutting down the process.