Private Assembly Directory Settings
If you've written and deployed a managed executable, you've probably deployed that executable and many of the assemblies it depends on to the same directory on disk. Similarly, if you've written a Microsoft ASP.NET application, you've probably deployed the code needed for your application to the bin directory under the site's virtual directory on the Web server. By deploying applications in this way, you're taking advantage of one of the key features of the Microsoft .NET Framework deployment model: the ability to deploy (almost) everything needed to run an application into the same directory. This deployment model has several benefits. It makes your application easier to install, uninstall, or replicate between machines. Furthermore, it enables you as an application developer to have tighter control over the dependencies that your application loads.
The key to providing this private deployment model is the ApplicationBase property on AppDomainSetup . When a host creates an application domain, this property is set to the root directory under which all dependent assemblies will be deployed. For example, the ASP.NET host sets ApplicationBase to the virtual root for the Web site. Similarly, the default CLR host sets the ApplicationBase for an executable to the directory on disk where the executable file is located. The following example sets the ApplicationBase for a new domain to a location in the Program Files directory:
using System; AppDomainSetup adSetup = new AppDomainSetup(); adSetup.ApplicationBase = @"c:\Program Files\MyApp"; AppDomain ad = AppDomain.CreateDomain("MyApp", null, adSetup);
Typically, the value of ApplicationBase is set to a fully qualified directory on the same machine on which the host is running. However, because an ApplicationBase can be any directory, you can also set it to a directory on a remote Web or file server. For example, you could set the ApplicationBase for a domain to http://www.cohowinery.com or \\cohowinery\myapp. When doing so, however, keep in mind that the security requirements for code running in the application domain are greater. Specifically, code loaded from a remote location obtains a lower level of trust by default than code running from the local machine.
If you don't provide a value for ApplicationBase when creating a new domain, the CLR will set ApplicationBase to the directory containing the executable file that caused the process to be created. For example, if you launch an executable file from c:\program files\myapp, that directory will be the default ApplicationBase for all domains created in the process.
Customizing the ApplicationBase Directory Structure
Once you've established the root directory for your new application domain, you can customize the subdirectories under the root in which the CLR will look for private assemblies by using the PrivateBinPath, PrivateBinPathProbe , and DisallowApplicationBaseProbing properties on AppDomainSetup .
By default, the CLR will look for dependencies directly in the
and in a subdirectory of the
that matches the simple
You can change the set of subdirectories the CLR looks in for dependencies by using the PrivateBinPath property on AppDomainSetup . PrivateBinPath is a semicolon-delimited list of subdirectories under the ApplicationBase in which you'd like the CLR to search for dependencies. Keep in mind that all directories specified using PrivateBinPath must be subdirectories of the ApplicationBase . You cannot use this property to cause assemblies to be loaded from outside of the ApplicationBase . Any subdirectories you supply using this property are searched in addition to the subdirectories the CLR would search by default. For example, the following code creates an application domain with an ApplicationBase of c:\program files\myapp and uses PrivateBinPath to add a subdirectory named bin to the list of subdirectories searched:
AppDomainSetup adSetup = new AppDomainSetup(); adSetup.ApplicationBase = @"c:\Program Files\MyApp"; adSetup.PrivateBinPath = "bin"; AppDomain ad = AppDomain.CreateDomain("one", null, adSetup);
Not only does this code cause the bin subdirectory to be searched, it also causes the CLR to look in subdirectories under bin named by assembly name. That is, the CLR applies the same searching rules to the new bin subdirectory that it applies to the
itself. If myapp.exe were to be run in this domain, the CLR would now look in the following directories for utils.dll (
There are two other techniques you can use to customize the layout of the directory structure under the ApplicationBase . First, you can specify additional directories to search using settings in an application configuration file. Configuration files are associated with domains by using the ConfigurationFile property on AppDomainSetup as described later in the chapter. You use the <probing/> element with the privatePath attribute to specify additional search directories. The directories you add using the configuration file are searched in addition to the directories specified using the AppDomainSetup.PrivateBinPath property. Here's a simple example of a configuration file that uses privatePath to add the bin directory to the search list:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="bin" /> </assemblyBinding> </runtime> </configuration>
For simple configuration files such as this one, editing the Extensible Markup Language (XML) directly using a text editor works great, but in more complex scenarios you might find it more
Figure 6-1. Editing settings in an application's Properties dialog box using the .NET Framework Configuration tool
The second alternative to using the
property to customize the private assembly search list is to use the
Turning Off ApplicationBase Searching
In some scenarios, you might not want the CLR to look for assemblies in the
directory structure at all. For example, as I discuss in Chapter 8, the CLR hosting APIs enable you to customize the assembly loading process to such an extent that you can define your own assembly storage formats and locations. CLR
has two properties to support scenarios such as these:
(easily the most poorly named setting of the bunch).
property you can use to prevent the CLR from looking for assemblies
AppDomainSetup adSetup = new AppDomainSetup(); adSetup.PrivateBinPathProbe = "*"; AppDomain ad = AppDomain.CreateDomain("No AppBase Domain", null, adSetup);