An
application domain is a unit of isolation for executing managed code.
For a better understanding, let’s make a comparison with the Win32
world. In Win32 you have processes. Each process is isolated from other
processes by the system so that a process cannot interfere with other
processes and with resources required by such processes. This prevents
process corruption and unexpected crashes. In .NET Framework
architecture the idea of isolation is provided by application domains,
so an application domain is the place where an assembly runs isolated
from other assemblies; when an application is started, the CLR creates
one application domain for it. Although a Win32 process can host
multiple application domains, when an assembly is executing within an
application domain, it cannot interfere with other assemblies within
different application domains, although application domains can
communicate with each other. One assembly can create multiple
application domains (which are handled by the CLR) and run separate
assemblies within such domains, as I will explain in next section.
Creating Application Domains and Executing Assemblies
You have basically two ways
for executing assemblies inside application domains: getting the
instance of the default application domain for the running assembly
(that is, your application) and creating a new application domain. The System.AppDomain class provides a shared property named CurrentDomain, of type System.AppDomain,
which represents the instance of the current application domain. You
get the instance and then execute the assembly as follows:
Dim currentDomain As AppDomain = AppDomain.CurrentDomain
currentDomain.ExecuteAssembly("AnotherApp.exe")
The AppDomain class exposes an instance ExecuteAssembly method that enables executing the specified assembly within an application domain. Generally executing an assembly in
the current application domain is not a good idea, because you cannot
unload the assembly when the execution has completed. Because of this,
a better approach is to create a new application domain. For now let’s
see how you can get information on application domains:
'Shows the AppDomain friendly name
Console.WriteLine(currentDomain.FriendlyName)
'Shows the AppDomain id within the process
Console.WriteLine(currentDomain.Id)
'Shows the working directory for the running
'assembly within the AppDomain
Console.WriteLine(currentDomain.BaseDirectory)
'Returns True if the code is classified as
'fully-trusted
Console.WriteLine(currentDomain.IsFullyTrusted)
Notice how you can interrogate some properties for retrieving application domain information. The AppDomain
class offers a number of other advanced properties that are not covered
here. A useful resource for finding information related to AppDomain properties is the MSDN Library: http://msdn.microsoft.com/enus/library/system.appdomain(VS.100).aspx.
Now it’s time to understand how it is possible to create new
application domains and execute assemblies. Basically you invoke the AppDomain.CreateDomain static method and then you invoke ExecuteAssembly.
The AppDomain class exposes a Load
method that also enables loading an assembly. According to the official
MSDN documentation, usage of this method should be always restricted to
COM interoperability scenarios. So always prefer ExecuteAssembly instead.
|
Also remember to unload
the application domain after loaded assemblies have completed their
work. The following code provides an example:
Dim secondDomain As AppDomain = AppDomain.
CreateDomain("secondDomain")
Try
secondDomain.ExecuteAssembly("MyApp.exe")
Catch ex As AppDomainUnloadedException
Console.WriteLine("The AppDomain was already unloaded")
Catch ex As Exception
Finally
Try
AppDomain.Unload(secondDomain)
Catch ex As CannotUnloadAppDomainException
Console.Write("Unable to unload the AppDomain")
End Try
End Try
The CLR throws an AppDomainUnloadedException
if the code attempts to access an already unloaded application domain.
As you can see from the code, you unload an application domain by
invoking the AppDomain.Unload
shared method that takes the application domain instance as an
argument. It is worth mentioning that, if the application domain cannot
be unloaded, a CannotUnloadAppDomainException is thrown. The AppDomain.CreateDomain method offers several overloads. One of them allows taking an argument of type AppDomainSetup
that is a special object that gives you the opportunity to set some
application domain properties. The following code provides an example:
Dim domainSetup As New AppDomainSetup
With domainSetup
'Sets the current directory for the AppDomain
.ApplicationBase = Environment.CurrentDirectory
'Sets the application name
.ApplicationName = "App domain demo"
'Allows assembly binding redirection
.DisallowBindingRedirects = False
'Disallows code download from assemblies
'via http
.DisallowCodeDownload = True
'Assigns a config file to the new app domain,
'in this case the app.config of the current domain
.ConfigurationFile = AppDomain.CurrentDomain.
SetupInformation.ConfigurationFile
End With
Dim thirdDomain As AppDomain = AppDomain.
CreateDomain("thirdDomain", Nothing, domainSetup)
Notice that the second argument is of type System.Security.Policy.Evidence
and is useful if you want to assign specific security policies to the
application domain. In this demonstrative code this is not
accomplished. For this particular topic, notice that application
domains are important for security policies that you apply to your
code. In the next section you learn about changes introduced in the
.NET Framework 4 to the managed security model.
In next chapter you learn
about Reflection, and you see how you can create assemblies and code at
runtime. When you have a dynamically created assembly with custom code,
you can execute the assembly within an application domain with the same
techniques shown in this section.
|