AppDomain 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
表示应用程序域,它是一个应用程序在其中执行的独立环境。 此类不能被继承。
public ref class AppDomain sealed : MarshalByRefObject
public ref class AppDomain : MarshalByRefObject
public ref class AppDomain sealed : MarshalByRefObject, _AppDomain, System::Security::IEvidenceFactory
public sealed class AppDomain : MarshalByRefObject
public class AppDomain : MarshalByRefObject
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
public sealed class AppDomain : MarshalByRefObject, _AppDomain, System.Security.IEvidenceFactory
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class AppDomain : MarshalByRefObject, _AppDomain, System.Security.IEvidenceFactory
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class AppDomain : MarshalByRefObject
type AppDomain = class
inherit MarshalByRefObject
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
type AppDomain = class
inherit MarshalByRefObject
interface _AppDomain
interface IEvidenceFactory
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type AppDomain = class
inherit MarshalByRefObject
interface _AppDomain
interface IEvidenceFactory
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type AppDomain = class
inherit MarshalByRefObject
Public NotInheritable Class AppDomain
Inherits MarshalByRefObject
Public Class AppDomain
Inherits MarshalByRefObject
Public NotInheritable Class AppDomain
Inherits MarshalByRefObject
Implements _AppDomain, IEvidenceFactory
- 继承
- 属性
- 实现
示例
此示例演示如何创建新 AppDomain类型、实例化该新 AppDomain类型并与该类型的对象通信。 此外,此示例演示如何卸载 AppDomain 导致对象被垃圾回收。
using namespace System;
using namespace System::Reflection;
using namespace System::Threading;
using namespace System::Security::Policy;
// Because this class is derived from MarshalByRefObject, a proxy
// to a MarshalByRefType object can be returned across an AppDomain
// boundary.
ref class MarshalByRefType : MarshalByRefObject
{
public:
// Call this method via a proxy.
void SomeMethod(String^ callingDomainName)
{
// Get this AppDomain's settings and display some of them.
AppDomainSetup^ ads = AppDomain::CurrentDomain->SetupInformation;
Console::WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}",
ads->ApplicationName,
ads->ApplicationBase,
ads->ConfigurationFile
);
// Display the name of the calling AppDomain and the name
// of the second domain.
// NOTE: The application's thread has transitioned between
// AppDomains.
Console::WriteLine("Calling from '{0}' to '{1}'.",
callingDomainName,
Thread::GetDomain()->FriendlyName
);
};
};
void main()
{
// Get and display the friendly name of the default AppDomain.
String^ callingDomainName = Thread::GetDomain()->FriendlyName;
Console::WriteLine(callingDomainName);
// Get and display the full name of the EXE assembly.
String^ exeAssembly = Assembly::GetEntryAssembly()->FullName;
Console::WriteLine(exeAssembly);
// Construct and initialize settings for a second AppDomain.
AppDomainSetup^ ads = gcnew AppDomainSetup();
ads->ApplicationBase = AppDomain::CurrentDomain->BaseDirectory;
ads->DisallowBindingRedirects = false;
ads->DisallowCodeDownload = true;
ads->ConfigurationFile =
AppDomain::CurrentDomain->SetupInformation->ConfigurationFile;
// Create the second AppDomain.
AppDomain^ ad2 = AppDomain::CreateDomain("AD #2",
AppDomain::CurrentDomain->Evidence, ads);
// Create an instance of MarshalbyRefType in the second AppDomain.
// A proxy to the object is returned.
MarshalByRefType^ mbrt =
(MarshalByRefType^) ad2->CreateInstanceAndUnwrap(
exeAssembly,
MarshalByRefType::typeid->FullName
);
// Call a method on the object via the proxy, passing the
// default AppDomain's friendly name in as a parameter.
mbrt->SomeMethod(callingDomainName);
// Unload the second AppDomain. This deletes its object and
// invalidates the proxy object.
AppDomain::Unload(ad2);
try
{
// Call the method again. Note that this time it fails
// because the second AppDomain was unloaded.
mbrt->SomeMethod(callingDomainName);
Console::WriteLine("Sucessful call.");
}
catch(AppDomainUnloadedException^)
{
Console::WriteLine("Failed call; this is expected.");
}
}
/* This code produces output similar to the following:
AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
*/
using System;
using System.Reflection;
using System.Threading;
class Module1
{
public static void Main()
{
// Get and display the friendly name of the default AppDomain.
string callingDomainName = Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
// Get and display the full name of the EXE assembly.
string exeAssembly = Assembly.GetEntryAssembly().FullName;
Console.WriteLine(exeAssembly);
// Construct and initialize settings for a second AppDomain.
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
ads.DisallowBindingRedirects = false;
ads.DisallowCodeDownload = true;
ads.ConfigurationFile =
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
// Create the second AppDomain.
AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);
// Create an instance of MarshalbyRefType in the second AppDomain.
// A proxy to the object is returned.
MarshalByRefType mbrt =
(MarshalByRefType) ad2.CreateInstanceAndUnwrap(
exeAssembly,
typeof(MarshalByRefType).FullName
);
// Call a method on the object via the proxy, passing the
// default AppDomain's friendly name in as a parameter.
mbrt.SomeMethod(callingDomainName);
// Unload the second AppDomain. This deletes its object and
// invalidates the proxy object.
AppDomain.Unload(ad2);
try
{
// Call the method again. Note that this time it fails
// because the second AppDomain was unloaded.
mbrt.SomeMethod(callingDomainName);
Console.WriteLine("Sucessful call.");
}
catch(AppDomainUnloadedException)
{
Console.WriteLine("Failed call; this is expected.");
}
}
}
// Because this class is derived from MarshalByRefObject, a proxy
// to a MarshalByRefType object can be returned across an AppDomain
// boundary.
public class MarshalByRefType : MarshalByRefObject
{
// Call this method via a proxy.
public void SomeMethod(string callingDomainName)
{
// Get this AppDomain's settings and display some of them.
AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}",
ads.ApplicationName,
ads.ApplicationBase,
ads.ConfigurationFile
);
// Display the name of the calling AppDomain and the name
// of the second domain.
// NOTE: The application's thread has transitioned between
// AppDomains.
Console.WriteLine("Calling from '{0}' to '{1}'.",
callingDomainName,
Thread.GetDomain().FriendlyName
);
}
}
/* This code produces output similar to the following:
AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
*/
open System
open System.Reflection
open System.Threading
// Because this class is derived from MarshalByRefObject, a proxy
// to a MarshalByRefType object can be returned across an AppDomain
// boundary.
type MarshalByRefType() =
inherit MarshalByRefObject()
// Call this method via a proxy.
member _.SomeMethod(callingDomainName) =
// Get this AppDomain's settings and display some of them.
let ads = AppDomain.CurrentDomain.SetupInformation
printfn $"AppName={ads.ApplicationName}, AppBase={ads.ApplicationBase}, ConfigFile={ads.ConfigurationFile}"
// Display the name of the calling AppDomain and the name
// of the second domain.
// NOTE: The application's thread has transitioned between
// AppDomains.
printfn $"Calling from '{callingDomainName}' to '{Thread.GetDomain().FriendlyName}'."
// Get and display the friendly name of the default AppDomain.
let callingDomainName = Thread.GetDomain().FriendlyName
printfn $"{callingDomainName}"
// Get and display the full name of the EXE assembly.
let exeAssembly = Assembly.GetEntryAssembly().FullName
printfn $"{exeAssembly}"
// Construct and initialize settings for a second AppDomain.
let ads = AppDomainSetup()
ads.ApplicationBase <- AppDomain.CurrentDomain.BaseDirectory
ads.DisallowBindingRedirects <- false
ads.DisallowCodeDownload <- true
ads.ConfigurationFile <-
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
// Create the second AppDomain.
let ad2 = AppDomain.CreateDomain("AD #2", null, ads)
// Create an instance of MarshalbyRefType in the second AppDomain.
// A proxy to the object is returned.
let mbrt =
ad2.CreateInstanceAndUnwrap(
exeAssembly,
typeof<MarshalByRefType>.FullName) :?> MarshalByRefType
// Call a method on the object via the proxy, passing the
// default AppDomain's friendly name in as a parameter.
mbrt.SomeMethod callingDomainName
// Unload the second AppDomain. This deletes its object and
// invalidates the proxy object.
AppDomain.Unload ad2
try
// Call the method again. Note that this time it fails
// because the second AppDomain was unloaded.
mbrt.SomeMethod callingDomainName
printfn "Sucessful call."
with :? AppDomainUnloadedException ->
printfn "Failed call this is expected."
(* This code produces output similar to the following:
AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call this is expected.
*)
Imports System.Reflection
Imports System.Threading
Module Module1
Sub Main()
' Get and display the friendly name of the default AppDomain.
Dim callingDomainName As String = Thread.GetDomain().FriendlyName
Console.WriteLine(callingDomainName)
' Get and display the full name of the EXE assembly.
Dim exeAssembly As String = [Assembly].GetEntryAssembly().FullName
Console.WriteLine(exeAssembly)
' Construct and initialize settings for a second AppDomain.
Dim ads As New AppDomainSetup()
ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
ads.DisallowBindingRedirects = False
ads.DisallowCodeDownload = True
ads.ConfigurationFile = _
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
' Create the second AppDomain.
Dim ad2 As AppDomain = AppDomain.CreateDomain("AD #2", Nothing, ads)
' Create an instance of MarshalbyRefType in the second AppDomain.
' A proxy to the object is returned.
Dim mbrt As MarshalByRefType = CType( _
ad2.CreateInstanceAndUnwrap(exeAssembly, _
GetType(MarshalByRefType).FullName), MarshalByRefType)
' Call a method on the object via the proxy, passing the default
' AppDomain's friendly name in as a parameter.
mbrt.SomeMethod(callingDomainName)
' Unload the second AppDomain. This deletes its object and
' invalidates the proxy object.
AppDomain.Unload(ad2)
Try
' Call the method again. Note that this time it fails because
' the second AppDomain was unloaded.
mbrt.SomeMethod(callingDomainName)
Console.WriteLine("Sucessful call.")
Catch e As AppDomainUnloadedException
Console.WriteLine("Failed call; this is expected.")
End Try
End Sub
End Module
' Because this class is derived from MarshalByRefObject, a proxy
' to a MarshalByRefType object can be returned across an AppDomain
' boundary.
Public Class MarshalByRefType
Inherits MarshalByRefObject
' Call this method via a proxy.
Public Sub SomeMethod(ByVal callingDomainName As String)
' Get this AppDomain's settings and display some of them.
Dim ads As AppDomainSetup = AppDomain.CurrentDomain.SetupInformation
Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", _
ads.ApplicationName, ads.ApplicationBase, ads.ConfigurationFile)
' Display the name of the calling AppDomain and the name
' of the second domain.
' NOTE: The application's thread has transitioned between
' AppDomains.
Console.WriteLine("Calling from '{0}' to '{1}'.", _
callingDomainName, Thread.GetDomain().FriendlyName)
End Sub
End Class
'This code produces output similar to the following:
'
' AppDomainX.exe
' AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
' AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
' Calling from 'AppDomainX.exe' to 'AD #2'.
' Failed call; this is expected.
注解
应用程序域(由 AppDomain 对象表示)有助于提供用于执行托管代码的隔离、卸载和安全边界。
使用应用程序域隔离可能会降低进程的任务。 如果执行任务的状态变得不稳定,则可以卸载该AppDomain任务AppDomain,而不会影响进程。 当进程必须长时间运行而不重新启动时,这一点很重要。 还可以使用应用程序域来隔离不应共享数据的任务。
如果将程序集加载到默认应用程序域中,则进程运行时无法从内存中卸载该程序集。 但是,如果打开第二个应用程序域来加载和执行程序集,则在卸载该应用程序域时会卸载该程序集。 使用此技术可以最大程度地减少偶尔使用大型 DLL 的长时间运行进程的工作集。
备注
在 .NET Core 上,实现 AppDomain 受设计限制,不提供隔离、卸载或安全边界。 对于 .NET Core,正好有一个 AppDomain。 隔离和卸载通过 AssemblyLoadContext。 安全边界应由进程边界和适当的远程处理技术提供。
多个应用程序域可以在单个进程中运行;但是,应用程序域和线程之间没有一对一关联。 多个线程可以属于单个应用程序域,虽然给定线程不局限于单个应用程序域,但在任何给定时间,线程在单个应用程序域中执行。
应用程序域是使用 CreateDomain 该方法创建的。 AppDomain 实例用于加载和执行 () 程序集 Assembly 。 当不再使用时 AppDomain ,可以卸载它。
该 AppDomain 类实现一组事件,使应用程序能够在加载程序集时、卸载应用程序域时或引发未经处理的异常时做出响应。
有关使用应用程序域的详细信息,请参阅 应用程序域。
此类实现和MarshalByRefObject_AppDomainIEvidenceFactory接口。
不应为 AppDomain 对象创建可远程包装器。 这样做可能会发布对该对象的 AppDomain远程引用,从而公开远程访问等 CreateInstance 方法,并有效地销毁代码 AppDomain访问安全性。 连接到远程的 AppDomain 恶意客户端可以访问自身有权访问的任何资源 AppDomain 。 不要为任何扩展 MarshalByRefObject 和实现恶意客户端可用于绕过安全系统的方法的类型创建可远程包装器。
注意
属性的 AppDomainSetup.DisallowCodeDownload 默认值为 false
. 此设置对服务不安全。 若要防止服务下载部分受信任的代码,请将此属性设置为 true
。
属性
ActivationContext |
获取当前应用程序域的激活上下文。 |
ApplicationIdentity |
获得应用程序域中的应用程序标识。 |
ApplicationTrust |
获取说明授予应用程序的权限以及应用程序是否拥有允许其运行的信任级别的信息。 |
BaseDirectory |
获取基目录,它由程序集冲突解决程序用来探测程序集。 |
CurrentDomain |
获取当前 Thread 的当前应用程序域。 |
DomainManager |
获得初始化应用程序域时主机提供的域管理器。 |
DynamicDirectory |
获取目录,它由程序集冲突解决程序用来探测动态创建的程序集。 |
Evidence |
获取与该应用程序域关联的 Evidence。 |
FriendlyName |
获取此应用程序域的友好名称。 |
Id |
获得一个整数,该整数唯一标识进程中的应用程序域。 |
IsFullyTrusted |
获取一个值,该值指示加载到当前应用程序域的程序集是否是以完全信任方式执行的。 |
IsHomogenous |
获取一个值,该值指示当前应用程序域是否拥有一个为加载到该应用程序域的所有程序集授予的权限集。 |
MonitoringIsEnabled |
获取或设置一个值,该值指示是否对当前进程启用应用程序域的 CPU 和内存监视。 一旦对进程启用了监视,则无法将其禁用。 |
MonitoringSurvivedMemorySize |
获取上次回收后保留下来的,已知由当前应用程序域引用的字节数。 |
MonitoringSurvivedProcessMemorySize |
获取进程中所有应用程序域的上次回收后保留下来的总字节数。 |
MonitoringTotalAllocatedMemorySize |
获取自从创建应用程序域后由应用程序域进行的所有内存分配的总大小(以字节为单位,不扣除已回收的内存)。 |
MonitoringTotalProcessorTime |
获取自从进程启动后所有线程在当前应用程序域中执行时所使用的总处理器时间。 |
PermissionSet |
已过时。
获取沙盒应用程序域的权限集。 |
RelativeSearchPath |
获取基目录下的路径,在此程序集冲突解决程序应探测专用程序集。 |
SetupInformation |
获取此实例的应用程序域配置信息。 |
ShadowCopyFiles |
获取应用程序域是否配置为影像副本文件的指示。 |
方法
事件
AssemblyLoad |
在加载程序集时发生。 |
AssemblyResolve |
在对程序集的解析失败时发生。 |
DomainUnload |
在即将卸载 AppDomain 时发生。 |
FirstChanceException |
当托管代码抛出异常时发生,在运行时在调用堆栈中搜索应用程序域中的异常处理程序之前。 |
ProcessExit |
当默认应用程序域的父进程存在时发生。 |
ReflectionOnlyAssemblyResolve |
当程序集的解析在仅限反射的上下文中失败时发生。 |
ResourceResolve |
当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。 |
TypeResolve |
在对类型的解析失败时发生。 |
UnhandledException |
当某个异常未被捕获时出现。 |
显式接口实现
_AppDomain.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr) |
将一组名称映射为对应的一组调度标识符。 |
_AppDomain.GetTypeInfo(UInt32, UInt32, IntPtr) |
检索对象的类型信息,然后可以使用该信息获取接口的类型信息。 |
_AppDomain.GetTypeInfoCount(UInt32) |
检索对象提供的类型信息接口的数量(0 或 1)。 |
_AppDomain.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr) |
提供对某一对象公开的属性和方法的访问。 |