在自定义 AppDomain 中附加内存程序集

Attach in-memory assembly in custom AppDomain

我已经创建了一个沙盒AppDomain:

public AppDomain CreateSandbox()
{
    var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase };
    var permissionSet = new PermissionSet(PermissionState.None);
    permissionSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.NoFlags));
    permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
    permissionSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted)); // TODO: Restrict IO
    var appDomain = AppDomain.CreateDomain("Sandbox", null, setup, permissionSet);
    return appDomain;
}

我还有一个从 byte[] fileData:

加载的程序集
var assembly = Assembly.Load(fileData);
var appDomain = CreateSandBox();

如何将此程序集或 fileData 字节加载到 appDomain 中然后使用它?

您可以使用新的 AppDomain 来完成它。您必须实例化一个 class(继承 MarshalByRefObject),它将 运行 在所选的 AppDomain 中并为您加载程序集。这涉及 .NET 远程处理。 Tell me more in this MSDN article。尽管它提到了部分受信任的代码,但大部分内容仍然适用。

在沙箱域中让 class 继承 MarshalByRefObject 运行ning 加载程序集非常重要,以防代码不是 trust-worthy。

Proxy/Sandbox/Helper Class

此 class 充当您在主 AppDomain(您创建 child 域的地方)中的代码 运行 与您希望 运行 在 sandbox/child 域中。使用 child 域时,出于安全原因,主域中的 objects 只能直接与 child 域中 运行ning 的代理 class 对话。

通信是在幕后通过 .NET Remoting 进行的 - 您可能不知道。因此,为什么 class 是 MarshalByRefObject.

例如(修改后的 MSDN 示例)

class Sandboxer:MarshalByRefObject
{
    public void LoadDodgyAssembly(string path) { ... }
}

主机代码

在创建 child AppDomain 的地方使用此代码。以下代码应 运行 在主 AppDomain 中:

var appDomain = CreateSandBox();

var handle = Activator.CreateInstanceFrom(
appDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
       typeof(Sandboxer).FullName );

var sandboxer = (Sandboxer) handle.Unwrap();
sandboxer.LoadDodgyAssembly("pleaserunme.dll");

Return 值

注意你的代理 class returns 到你在主 AppDomain 中的调用代码。如果您不信任加载的程序集,最好将您的方法标记为 void,否则请考虑使用您自己的可信任类型标记为 [Serializable]。

告诉我更多

大约在 2005 年左右,MSDN 杂志中有一篇精彩的文章,标题为 "Add-ins: 你相信它吗" 或类似但找不到的文章。