为什么新的 AppDomain 会加载不必要的 DLL?

Why does a new AppDomain load unnecessary DLLs?

我有一个 asp.net 网络 api,它具有执行一些动态生成的 DLL 的逻辑。 我想创建一个具有受限权限集的新沙盒 AppDomain 来执行这些 DLL。

这是创建新的受限应用域的方法:

public static AppDomain CreateRestrictedDomain(string applicationBasePath)
{
    PermissionSet permissionSet = new PermissionSet(PermissionState.None);
    permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
    permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, applicationBasePath));

    AppDomainSetup appDomainSetup = new AppDomainSetup
    {
        ApplicationBase = applicationBasePath,
        DisallowCodeDownload = true,
        DisallowBindingRedirects = true,
        DisallowPublisherPolicy = true,
        LoaderOptimization = LoaderOptimization.MultiDomainHost,
    };


    AppDomain restrictedDomain = AppDomain.CreateDomain(
        friendlyName: "MySandbox",
        securityInfo: null,
        info: appDomainSetup,
        grantSet: permissionSet,
        fullTrustAssemblies: null);

    return restrictedDomain;
}

我遇到的问题是第一次引用新的 appDomain 时,例如只是为了读取 appDomain.FriendlyName,框架尝试将当前应用程序中存在的一些依赖项加载到新的 AppDomain。如果依赖项不在 GAC 中,它会尝试在 applicationBasePath 中查找它们,但会失败,因为 applicationBasePath 设置为仅存储不受信任的 DLL 的文件夹。

我的问题是为什么创建新的 AppDomain 会触发加载这些额外的依赖项。在我上面的 CreateRestrictedDomain 方法中,没有引用任何这些依赖项。

我在 VS 2013 中使用默认模板创建了一个新的 asp.net 项目,在 Index 控制器中我只是使用上面的代码创建了一个新的 AppDomain,并打印出名称。这是代码:

public ActionResult Index()
{
    var tempPath = Path.GetTempPath();
    var untrustedPath = Path.Combine(tempPath, "unstrusted");
    if (!Directory.Exists(untrustedPath))
    {
        Directory.CreateDirectory(untrustedPath);
    }
    var appDomain = AppDomainSandboxHelper.CreateRestrictedDomain(untrustedPath);
    var friendlyName = appDomain.FriendlyName;
    ViewBag.Title = friendlyName;

    return View();
}

当我 运行 处于调试模式时,我可以看到读取 appDomain.FriendLyName 的行会触发 System.Web.dll 加载到新的 AppDomain "MySandbox"

'iisexpress.exe' (CLR v4.0.30319: Domain 4): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. Symbols loaded.

'iisexpress.exe' (CLR v4.0.30319: MySandbox): Loaded 'C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll'. Symbols loaded.

为什么 System.Web.dll 需要加载到新的 AppDomain ?

securityInfo 传递 null 使用当前正在执行的 AppDomain 的证据。

AppDomain.CreateDomain:

securityInfo

Type: System.Security.Policy.Evidence

Evidence that establishes the identity of the code that runs in the application domain. Pass null to use the evidence of the current application domain.

可能需要加载 System.Web.dll 程序集以检查其证据。

原来是因为我在现有的 ASP.NET 拥有的 AppDomain 中创建了一个 AppDomain。 ASP.NET 将自己的 AppDomainManager 安装到父 AppDomain 中,并且它会自动向下传播到子 AppDomain,除非像下面这样被调用者显式覆盖

AppDomainSetup appDomainSetup = new AppDomainSetup
{
    ApplicationBase = applicationBasePath,
    DisallowCodeDownload = true,
    DisallowBindingRedirects = true,
    DisallowPublisherPolicy = true,
    LoaderOptimization = LoaderOptimization.MultiDomainHost,
    AppDomainManagerAssembly = "", // overridden by caller
    AppDomainManagerType = "" // overridden by caller
};