Traditional Windows based development has considered the process as the basic unit of execution and isolation for running applications. The basic theory was that each running application was loaded into a separate process that automatically isolated each application from others. If for example, an error occurred in a single application, that wouldn’t affect the others running on the system. Essentially, a process defined a security boundary that also prevented applications from talking directly with each other. This actually worked quite well and helped to solve the perpetual tug of war that existed between scalability and fault tolerant systems. With the advent of the .NET runtime this concept was enhanced to include a new type of entity called the Application Domain. Much like the process, the Application Domain is designed as a security boundary that confines errors and faults to a specific domain. In this article, we will cover some of the basics of the Application Domain and look at some of the system services it provides the .NET Runtime.
Although, it is similar to the process, the Application Domain has somewhat different characteristics. By design the Application Domain is considered to be much lighter than the traditional Windows based process. Ideally, Application Domains are perfect for application scenarios that require isolation without the heavy overhead associated with the traditional application process. Also, by the definition discussed above, the process runs exactly one application. Of course this is contrast to the Common Language Runtime (CLR) within the .NET Framework that enables multiple applications to run within a single process. The Framework accomplishes this by loading each application into a separate Application Domain and verifying that all user code in an Application Domain is considered type safe. The Application Domain is designed as a virtual process that serves to isolate applications. By default each .NET Framework application within an Application Domain runs under the control of a host that creates and loads the assemblies. This guarantees that each application is independent and isn’t able to directly access resources within another domain. The application host is then able to access evidentiary information like the code loading location, digital signatures, and version of any application code that it loads. This evidence is what the Common Language Runtime uses to make decisions when applying the security policy. Each bit of evidence indicates to the runtime that code has a particular characteristic. Based on the supplied evidence both the assemblies and Application Domains receive a set of permission grants.
Inside the Framework
Within the actual Framework, the System.AppDomain class provides the Application Domain functionality used by the hosts. An Application domain, which is represented by AppDomain objects, helps to provide the necessary isolation for unloading and security boundaries managed code execution. Multiple Application Domains are able to run in a single process. However, there isn’t a one to one correlation between application domains and threads. Several threads can belong to a single Application Domain. While a given thread is not confined to a single application domain, at any given time, a thread executes in a single application domain.
The Windows operating system does not directly 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. Application domains are created using the CreateDomain method from within one of the possible application hosts as shown in Table 1.1. AppDomain instances are used to load and execute assemblies. Once the AppDomain is no longer used, it can be unloaded. The AppDomain class implements a set of events that enables applications to respond when an assembly is loaded, unloaded or when an unhandled exception is thrown.
Table 1.1 Types of application hosts
Application Host Type
Custom designed hosts
A managed or native code application that creates a domain and loads assemblies. For example, the Compact Framework is instantiated this way.
Domains created within the context of a web site. For example, an ISAPI filter ships with ASP.NET.
Launches applications from the shell. When a managed application is launched from a shell, a piece of unmanaged code loads the CLR and transitions control of the application to the CLR.
Once an application domain is created the host provides the ability to specify a security policy that is applied to code that runs within the Application Domain. This security policy is always subject to the any of the pre-defined policies. For obvious security reasons a host does have the ability to reduce a specific set of permissions but can’t by default grant additional permissions it doesn’t already have. Policy can be set only once for an Application domain. In order to set Application domain policy the host must be granted the security permissions that is provided through the SecurityPermission class for controlling domain policy. After an application domain policy is set, all subsequently loaded assemblies are granted permissions under the new policy. However, any previously loaded assemblies derive their permission grants under the pre-existing policy. By default, the permissions granted to these assemblies are not reevaluated under the new application domain policy.
A trusted host can provide information or evidence to the runtime about assemblies that are loaded into the application domain. If a domain host does not have the appropriate SecurityPermission for controlling evidence, the runtime uses the security enforced on the host to determine the security to enforce on the assembly.
In some situations, evidence that would normally be provided by a trusted application domain host is actually provided by the loader. Typically, after an application domain is created, the application domain host loads the first (main) assembly into the application domain and calls into that assembly to begin execution. When code in the first assembly references code in another assembly, the loader resolves the reference, loads the appropriate assembly into the application domain, and supplies the evidence about the assembly to the runtime. In this situation, the trusted application domain host that provided the evidence for the original assembly does not provide evidence to subsequently loaded assemblies.
The AppDomainSetup Class is used to provide the common language runtime with configuration information for a new Application Domain. Probably the most important thing to keep in mind when creating Application Domains is setting the ApplicationBase property. This directory location serves as the application root and identifies the starting point for the assembly manager when looking for other assemblies. Once set, this property cannot be changed after the Application Domain has finished loading. It is always important to keep in mind that this location can directly influence which permissions are granted to an Application Domain. For example, an Application Domain that originates on the local machine automatically receives full trust. However, if the ApplicationBase is set to the path of an Intranet directory, the default settings will restrict the permission set to the permission set granted to the local Intranet.
Always keep in mind that that any new Application Domains will by default only inherit the ApplicationBase property of its creator..
For example, the following code creates a new Application Domain when a button is clicked within a Windows Form application.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Create application domain setup information.
Dim MyDomainInfo As New AppDomainSetup
MyDomainInfo.ApplicationBase = "C:\testapp"
' Create the application domain.
Dim domain As AppDomain = AppDomain.CreateDomain("MyNewDomain", Nothing, Mydomaininfo)
' Show Application domain information
MsgBox("Application base is: " + domain.SetupInformation.ApplicationBase)
MsgBox("Host domain: " + AppDomain.CurrentDomain.FriendlyName)
MsgBox("child domain: " + domain.FriendlyName)
' Unload the application domain.
The Application Domain that is created is parented to the current running application. However, it operates as a separate entity that can be shut down and controlled independent of the current application. This article certainly hasn’t covered the full breath of the possibilities of the Application Domain. However, it should have provided a brief understanding of some of the key concepts that are associated with this concept.