Questions and Answers
What is an application domain?
Application domain is a construct in the CLR that is the unit of isolation for an application. The
isolation guarantees the following:
An application can be independently stopped.
An application cannot directly access code or resources in another application.
A fault in an application cannot affect other applications.
Configuration information is scoped by application. This means that an application controls
the location from which code is loaded and the version of the code that is loaded.
For more information see COM+ Application Domains.
What is the difference between an application domain and a
process?
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.
For more information see COM+ Application Domains.
What is a CLR host?
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:
[Link]. An ISAPI filter that ships with [Link] 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.
What is a default domain?
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.
An assembly consists of the following two logical elements:
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.
For more information see Assembly Overview.
How do I run managed code in a process?
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.
For more information see Hosting the Common Language Runtime.
What is the purpose of the System._AppDomain interface?
The System._AppDomain interface is meant for use by unmanaged code that needs access to
the members of the managed [Link] 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.
How do I create an application domain?
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 [Link] class:
1. public static AppDomain CreateDomain(String friendlyName)
2. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo)
3. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo,
AppDomainSetup info)
4. public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo, String
appBasePath, String appRelativeSearchPath, bool shadowCopyFiles)
Overload 1 allows an application domain to be created given its name. Overloads 2-3 allow a
[Link] object to be supplied to CreateDomain to define the security
policy for the application. Overload 3 allows a [Link] 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 [Link] object.
How do I configure how assemblies are loaded into an application
domain?
An application domain is configured by supplying a [Link] object to the
following static method of the [Link] class:
public static AppDomain CreateDomain(String friendlyName, Evidence securityInfo,
AppDomainSetup info)
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;
AppDomainSetup info = new AppDomainSetup();
[Link] = C:\\Program Files\\MyApp;
[Link] = C:\\Program Files\\MyApp\\[Link];
AppDomain appDomain = [Link](MyDomain, null, info);
How do I retrieve configuration information about an an application
domain?
Use the following property of the [Link] class.
public AppDomainSetup SetupInformation { get; }
How do I define the security policy for an application domain?
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.
A host can control policy in two ways:
First, the host can provide evidence to an application domain when it is created by supplying an
Evidence object to [Link]. 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 [Link];
Evidence evidence = new Evidence();
[Link](new URL(http:://[Link]);
AppDomain appDomain = [Link](MyDomain, evidence);
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 [Link] is used to specify security
policy. For more information and an example of how to use the method, see Hosting the Common
Language Runtime.
How do I retrieve the evidence for an application domain?
Use the following property of the [Link] class.
public Evidence Evidence { get; }
How do I execute an application in a remote application domain?
The [Link] 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)
2. public int ExecuteAssembly(String assemblyFile, Evidence assemblySecurity)
3. public int ExecuteAssembly(String assemblyFile)
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
[Link] 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:
Create the remote application domain using [Link]. Optionally
specify the following:
o Configuration information such as ApplicationBase to control where assemblies are
searched for during loading.
o Evidence to control specific actions of the code executed in the application domain.
Execute the assembly using [Link] on the application
domain created in the previous step.
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: [Link]
// Creates a remote application domain and executes an assembly
// within that application domain.
using System;
using [Link];
using [Link];
public class ExecAssembly
public static void Main( String[] argv )
// Set ApplicationBase to the current directory
AppDomainSetup info = new AppDomainSetup();
[Link] = "[Link] + [Link];
// Create an application domain with null evidence
AppDomain dom = [Link]("RemoteDomain", null, info);
// Tell the AppDomain to execute the assembly
[Link]("[Link]");
// Clean up by unloading the application domain
[Link](dom);
The HelloWorld1 assembly contains the following code:
// C# Sample Code
// File: [Link]
using System;
using [Link];
public class HelloWorld
{
public void SayHello(String greeting)
[Link]("In the application domain: " + [Link]().FriendlyName);
[Link](greeting);
public static void Main( String[] argv )
HelloWorld o = new HelloWorld();
[Link]("Hello World!");
Compile [Link] and [Link] as follows:
csc [Link]
csc [Link]
How do I invoke a method in a remote application domain?
The steps necessary to invoke a method in a remote application domain are as follows:
Create the remote application domain using [Link]. Optionally
specify the following:
o Configuration information such as ApplicationBase to control where assemblies are
searched for during loading.
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
[Link]. This is necessary to ensure that the type is marshaled by reference
across the boundary of the created application domain.
Call [Link] to create an instance of the parent type of the
method in the application domain created in the previous step. CreateInstance will return a
wrapped object reference (ObjectHandle) that needs to be unwrapped before it can be used.
Unwrap the ObjectHandle to obtain an Object reference to invoke methods on the type.
The [Link] class provides the following methods for instantiating a type:
1. public ObjectHandle CreateInstance(String assemblyName, String typeName)
2. public ObjectHandle CreateInstance(String assemblyName, String typeName, Object[]
activationAttributes)
3. public ObjectHandle CreateInstance(String assemblyName, String typeName, bool
ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)
4. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName)
5. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName, Object[]
activationAttributes)
6. public ObjectHandle CreateInstanceFrom(String assemblyFile, String typeName, bool
ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)
The difference between CreateInstance and CreateInstanceFrom is that CreateInstances first
parameter is the simple name of an assembly while the first parameter to CreateInstanceFrom is
the path name of the assembly. The first method calls the static method [Link] while the
second method calls the static method [Link]. See loading of assemblies for
additional details.
The [Link] class also provides the following convenience methods that combine the
operations of instantiating a type and unwrapping the ObjectHandle:
1. public Object CreateInstanceAndUnwrap(String assemblyName, String typeName)
2. public Object CreateInstance(String assemblyName, String typeName, Object[]
activationAttributes)
3. public Object CreateInstance(String assemblyName, String typeName, bool ignoreCase,
BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)
4. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName)
5. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName,
Object[] activationAttributes)
6. public Object CreateInstanceFromAndUnwrap (String assemblyFile, String typeName, bool
ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes, Evidence securityAttributes)
The following code snippet shows how to invoke the SayHello method in the HelloWorld2
assembly:
// C# Sample Code
// File: [Link]
// Creates a remote application domain and invokes a method
// within an assembly in that application domain.
using System;
using [Link];
using [Link];
public class InvokeMethod
public static void Main( String[] argv )
// Set ApplicationBase to the current directory
AppDomainSetup info = new AppDomainSetup();
[Link] = "[Link] + [Link];
// Create an application domain with null evidence
AppDomain dom = [Link]("RemoteDomain", null, info);
// Load the assembly HelloWorld2 and instantiate the type
// HelloWorld
BindingFlags flags = ([Link] | [Link] |
[Link]);
ObjectHandle objh = [Link]("HelloWorld2", "HelloWorld", false, flags, null, new
String[]{"Hello World!"}, null, null, null);
if (objh == null) {
[Link]("CreateInstance failed");
return;
// Unwrap the object
Object obj = [Link]();
// Cast to the actual type
HelloWorld h = (HelloWorld)obj;
// Invoke the method
[Link]();
// Clean up by unloading the application domain
[Link](dom);
}
The HelloWorld2 assembly contains the following code:
// C# Sample Code
// File: [Link]
using System;
using [Link];
public class HelloWorld : MarshalByRefObject
private String _greeting;
public HelloWorld(String greeting)
if (greeting == null) {
throw new ArgumentNullException("Null greeting!");
_greeting = greeting;
public void SayHello()
[Link]("In the application domain: " + [Link]().FriendlyName);
[Link](_greeting);
}
Compile [Link] and [Link] as follows:
csc /t:library [Link]
csc /r:[Link] [Link]
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.
How do I load an assembly into an application domain?
The [Link] and the [Link] classes provide many overloads
for loading an assembly into an application domain. The [Link] methods are
primarily meant for COM Interoperability use. However, they can be used safely to load an
assembly into the current application domain.
An attempt to call [Link] 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 [Link]) 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 [Link] provides the following methods for loading an assembly into an
application domain:
1. public Assembly Load(AssemblyName assemblyRef)
2. public Assembly Load(AssemblyName assemblyRef, Evidence evidence)
3. public Assembly Load(AssemblyName assemblyRef, Evidence evidence, String
callerLocation)
4. public Assembly Load(byte[] rawAssembly)
5. public Assembly Load(byte[] rawAssembly, byte[] rawAssemblyStore)
6. public Assembly Load(byte[] rawAssembly, byte[] rawAssemblyStore, Evidence evidence)
7. public Assembly Load(String assemblyName)
8. public Assembly Load(String assemblyName, Evidence evidence)
9. public Assembly Load(String assemblyName, Evidence evidence, String callerLocation)
Note. Overloads 3 and 9 are obsolete and will be removed in a future release.
Overloads 1-3 require the caller to supply an [Link] object that
specifies what assembly is to be loaded. See the description of the class in the BCL reference
documentation for the details. Overload 2, 6, and 8 allow the caller to supply evidence for the
assembly code that will execute in the application domain. Overloads 4-6 are used to load a
COFF-based image containing an emitted assembly and optionally specify the raw bytes
representing the symbols for the assembly. In overloads 7-9, the assemblyName parameter
should be an assembly name and not the path or filename of the requested assembly.
assemblyName does not include an extension such as .DLL or .EXE.
Some examples of AssemblyName include the following:
A simply named assembly with a default culture:
[Link], Culture=
A fully specified reference for strong named assembly with culture en:
[Link], Culture=en, PublicKeyToken=a5d015c7d5a0b012, Version=[Link]
Partially specified AssemblyName which may be satisfied by either strong or simply named
assembly:
[Link]
[Link], Culture=""
[Link], Culture=en
The [Link] class provides the following static methods for loading an
assembly into the current application domain:
1. public static Assembly Load(AssemblyName assemblyRef)
2. public static Assembly Load(AssemblyName assemblyRef, Evidence evidence)
3. public static Assembly Load(AssemblyName assemblyRef, Evidence evidence, String
callerLocation)
4. public static Assembly Load(byte[] rawAssembly)
5. public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore)
6. public static Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore, Evidence evidence)
7. public static Assembly Load(String assemblyName)
8. public static Assembly Load(String assemblyName, Evidence evidence)
9. public static Assembly Load(String assemblyName, Evidence evidence, String
callerLocation)
[Link] static Assembly LoadFrom(String assemblyFile)
[Link] static Assembly LoadFrom(String assemblyFile, Evidence evidence)
Note. Overloads 3 and 9 are obsolete and will be removed in a future release. Overload 1-9 of
[Link] are similar to the overloads 1-9 of [Link] with the difference that the
static [Link] methods load the specified assembly into the current application domain
while the instance [Link] methods load the specified assembly into the target
application domain. The same restriction on the assemblyName parameter that applied to
[Link] 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 [Link] do not interfere with direct
dependencies of the managed application (obtained using [Link]), 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 [Link] as well as the transitive
closure of their dependencies. For more information about load contexts, consult the SDK
documentation.
Note. The [Link] class does not provide LoadFrom methods similar to the
[Link] 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 [Link] using the file name of the
assembly to be loaded into the target application domain.
Execute the stub assembly in the target application domain using
[Link].
How do I dynamically resolve assemblies, types, and resources?
The assembly resolution is controlled by the configuration properties for the application domain
such as [Link]. 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 [Link] event to hook into the type loading process.
The AssemblyResolve event is defined as follows:
public event ResolveEventHandler AssemblyResolve
where [Link] is defined as follows:
public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args)
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
[Link].
The following sample code shows how to define a handler to resolve an assembly dynamically:
// C# Sample Code
// File [Link]
// Illustrates how to resolve an assembly dynamically.
using System;
using [Link];
using [Link];
using [Link];
using [Link];
public class AssemblyResolve
// This method invokes the "SayHello" method on the
// type "HelloWorld" of an assemby "DynamicHelloWorld".
// The assembly does not exist on the disk but is created
// on the fly by the assembly resolution handler.
public static void Main( String[] argv )
// Define the handler for resolving the assembly
AssemblyResolve assemblyResolve = new AssemblyResolve();
ResolveEventHandler hndlr = new
ResolveEventHandler([Link]);
AppDomain dom = [Link]();
[Link] += hndlr;
// Attempt to load the assembly. This should trigger the
// handler when the assembly is not found on disk.
// Load the assembly HelloWorld
Assembly asm = [Link]("DynamicHelloWorld");
if (asm == null) {
[Link]("Main: Can't load assembly HelloWorld");
return;
// Lookup the type in the loaded assembly
Type t = [Link]("HelloWorld");
if (t == null) {
[Link]("Main: Can't find type HelloWorld");
return;
// Instantiate the type HelloWorld
Object o = [Link](t, null);
// Use Reflection, to invoke the "SayHello" method
[Link]("SayHello", [Link] | [Link] |
[Link], null, o, null);
// The handler uses Reflection Emit to dynamically build
// the "DynamicHelloWorld" assembly with the type "HelloWorld"
public Assembly AssemblyResolver(Object sender, ResolveEventArgs args)
{
// Write message that we are in the assembly resolver
[Link]("AssemblyResolver: Building assembly" + [Link] + "...");
// Define the dynamic assembly
AssemblyName asmName = new AssemblyName();
[Link] = "DynamicHelloWorld";
AssemblyBuilder asm = [Link]().DefineDynamicAssembly(asmName,
[Link]);
// Define a dynamic module in the assembly
ModuleBuilder mod = [Link]("DynamicHelloWorld");
// Define the "HelloWorld" type in the module
TypeBuilder typ = [Link]("HelloWorld", [Link]);
// Define the "SayHello" method
MethodBuilder meth = [Link]("SayHello", [Link], null, null);
ILGenerator il = [Link]();
[Link]("Hello World!");
[Link]([Link]);
// Complete the type and return the dynamic assembly
[Link]();
[Link]("Returning dynamic assembly");
return asm;
Compile [Link] as follows:
csc [Link]
A type is resolved dynamically by defining a handler for the TypeResolve event. The
TypeResolve event is defined as follows:
public event ResolveEventHandler TypeResolve
A resource is resolved dynamically by defining a handler for the ResourceResolve event. The
ResourceResolve event is defined as follows:
public event ResolveEventHandler ResourceResolve
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.
How do I unload an assembly?
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.
How do I unload an application domain?
You should use the following static method in the [Link] class:
public static void Unload(AppDomain domain)
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.