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
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
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 和 .NET 5+ 上,实现 AppDomain 受设计限制,不提供隔离、卸载或安全边界。 这些版本只有一个 AppDomain。 隔离和卸载通过 AssemblyLoadContext提供。 安全边界应由进程边界和适当的远程处理技术提供。
多个应用程序域可以在单个进程中运行;但是,应用程序域和线程之间没有一对一关联。 多个线程可以属于单个应用程序域,而给定线程在任何给定时间都不会局限于单个应用程序域,但线程在单个应用程序域中执行。
应用程序域是使用 CreateDomain 该方法创建的。 AppDomain 实例用于加载和执行程序集(Assembly)。 当不再使用时 AppDomain ,可以卸载它。
该 AppDomain 类实现一组事件,使应用程序能够在加载程序集、卸载应用程序域时或引发未经处理的异常时响应。
有关使用应用程序域的详细信息,请参阅 应用程序域。
此类实现 MarshalByRefObject接口 _AppDomain和 IEvidenceFactory 接口。
不应为 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) |
提供对对象公开的属性和方法的访问。 |