加载字节数组程序集 [英] Loading Byte Array Assembly

查看:25
本文介绍了加载字节数组程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试仅使用字节数组加载程序集,但我不知道如何让它正常工作.这是设置:

I'm experimenting with loading an assembly using just byte arrays, but I can't figure out how to get it to work properly. Here is the setup:

public static void Main() 
{
    PermissionSet permissions = new PermissionSet(PermissionState.None);
    AppDomainSetup setup = new AppDomainSetup { ApplicationBase = Environment.CurrentDirectory };
    AppDomain friendlyDomain = AppDomain.CreateDomain("Friendly", null, setup, permissions);

    Byte[] primary = File.ReadAllBytes("Primary.dll_");
    Byte[] dependency = File.ReadAllBytes("Dependency.dll_");

    // Crashes here saying it can't find the file.
    friendlyDomain.Load(dependency);

    AppDomain.Unload(friendlyDomain);

    Console.WriteLine("Stand successful");
    Console.ReadLine();
}

我创建了两个模拟 dll,并有意将它们的扩展名重命名为.dll_",因此系统将无法找到物理文件.primarydependency 都正确填充,但是当我尝试使用二进制数据调用 AppDomain.Load 方法时,它返回:

I created two mock dlls, and renamed their extension to '.dll_' intentionally so the system wouldn't be able to find the physical files. Both primary and dependency fill correctly, but when I try to call the AppDomain.Load method with the binary data, it comes back with:

无法加载文件或程序集依赖项,版本=1.0.0.0,文化=中性,PublicKeyToken=null"或其依赖项之一.系统找不到指定的文件.

为什么要在系统中搜索文件?

Why would it be searching the system for a file?

更新

另一方面,这似乎有效:

This on the other hand seems to work:

public class Program {
    public static void Main() {
        PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
        AppDomainSetup setup = new AppDomainSetup { ApplicationBase = Environment.CurrentDirectory };
        AppDomain friendlyDomain = AppDomain.CreateDomain("Friendly", null, setup, permissions);

        Byte[] primary = File.ReadAllBytes("Primary.dll_");
        Byte[] dependency = File.ReadAllBytes("Dependency.dll_");

        // Crashes here saying it can't find the file.
        // friendlyDomain.Load(primary);

        Stage stage = (Stage)friendlyDomain.CreateInstanceAndUnwrap(typeof(Stage).Assembly.FullName, typeof(Stage).FullName);
        stage.LoadAssembly(dependency);

        Console.WriteLine("Stand successful");
        Console.ReadLine();
    }

}

public class Stage : MarshalByRefObject {
    public void LoadAssembly(Byte[] data) {
        Assembly.Load(data);
    }
}

所以看起来AppDomain.LoadAssembly.Load 之间是有区别的.

So it appears there is a difference between AppDomain.Load and Assembly.Load.

推荐答案

这是正常的,CLR 在搜索主要"需要的程序集时不会将您加载的依赖项"视为合适的程序集.与加载上下文"相关的问题,像这样加载的程序集没有.这是有意为之,CLR 无法确保 DLL Hell 不会成为问题,因为它不知道程序集来自何处.既然你打开了 DLL 地狱的大门,那么你自己也必须避开地狱.

This is normal, the CLR doesn't consider the "dependency" you loaded to be a suitable assembly when it searches for the assembly that "primary" needs. A problem associated with "loading context", there isn't one for assemblies loaded like this. This is intentional, the CLR cannot ensure that DLL Hell won't be an issue since it has no idea where the assembly came from. Since you opened the door to DLL Hell, you also have to avoid hell yourself.

您需要实现 AppDomain.AssemblyResolve 事件.它会在 CLR 找不到依赖项"时触发,您可以返回从 Assembly.Load(byte[]) 获得的程序集.但是,当它为同一个程序集触发多次时,您必须始终如一地执行此操作,换句话说,返回完全相同的程序集,否则您将遇到更多由 .NET 类型标识引起的问题.产生难以理解的转换异常,不能将 Foo 转换为 Foo"风格.

You'll need to implement the AppDomain.AssemblyResolve event. It will fire when the CLR cannot find "dependency", you can return the assembly you get from Assembly.Load(byte[]). You will however have to do so consistently when it fires more than once for the same assembly, in other words return the exact same Assembly, or you'll have more problems induced by .NET type identity. Producing hard to understand casting exceptions, "can't cast Foo to Foo" style.

还有其他问题,效率很低.程序集的虚拟内存不能由磁盘上的文件支持,因此它由页面文件支持.这会增加流程的提交大小.

There are other problems, it is rather inefficient. The virtual memory for the assembly cannot be backed by a file on disk so it is backed by the paging file. Which increases the commit size for your process.

最好不要这样做.

这篇关于加载字节数组程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆