将字节数组程序集加载到新的AppDomain中会引发FileNotFound异常 [英] Loading byte array assembly into new AppDomain throws a FileNotFound exception

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

问题描述

我正在尝试执行以下操作:

I'm trying to do the following:


  • 下载包含我需要执行的程序集的字节数组。
  • Download a byte array that contains an assembly that I need to execute.
  • Load an object from this assembly in a new app domain and execute method on the object

此处是我的代码,试图将程序集加载到新的应用程序域中:

Here is my code that attempts to load the assembly into new app domain:

    public object Execute(byte[] agentCode)
    {
        var app = AppDomain.CreateDomain("MonitoringProxy", AppDomain.CurrentDomain.Evidence, new AppDomainSetup {ApplicationBase = AppDomain.CurrentDomain.BaseDirectory}, new PermissionSet(PermissionState.Unrestricted));
        app.AssemblyResolve += AppOnAssemblyResolve;
        var assembly = app.Load(agentCode);

代码库在最后一行消失,并显示以下消息:

The codebase dies on the last line with the following message:


其他信息:无法加载文件或程序集
'Alertera.AgentProxy,版本= 1.0.0.0,区域性=中性,
PublicKeyToken = null'或它的依赖项之一。系统无法
找到指定的文件。

Additional information: Could not load file or assembly 'Alertera.AgentProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

没有代码会命中AppOnAssemblyResolve函数。
有趣的是,它已经正确读取了程序集的名称。此外,Alertera.AgentProxy程序集除了System和Newtonsoft.Json之外,没有任何外部依赖项。但是,Newtsoft.Json已作为资源嵌入其中,因此不需要单独加载。

No code ever hits the AppOnAssemblyResolve function. What's interesting is that it has read the name of the assembly properly. Furthermore, Alertera.AgentProxy assembly does not have any external dependencies, except on System and Newtonsoft.Json. However, Newtsoft.Json has been imbedded into it as a resource, so it does not need to be loaded separately.

任何指针吗?使用.NET 2实现最大兼容性

Any pointers? Using .NET 2 for maxmimum compatibility

推荐答案

也许使用应用程序域上的回调切换到新创建的应用程序的上下文域将允许您成功加载?像这样...

Maybe using the callback on the app domain to switch to the context of the newly created app domain will allow you to load successfully? Something like this...

    public object Execute(byte[] assemblyBytes)
    {
        AppDomain domainWithAsm = AsmLoad.Execute(assemblyBytes);
        ....
    }

    [Serializable]
    public class AsmLoad
    {
        public byte[] AsmData;

        public void LoadAsm() 
        {
            Assembly.Load(AsmData);
            Console.WriteLine("Loaded into: " + AppDomain.CurrentDomain.FriendlyName);
        }

        public static AppDomain Execute(byte[] assemblyBytes)
        {
            AsmLoad asmLoad = new AsmLoad() { AsmData = assemblyBytes };
            var app = AppDomain.CreateDomain("MonitoringProxy", AppDomain.CurrentDomain.Evidence, new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory }, new PermissionSet(PermissionState.Unrestricted));
            app.DoCallBack(new CrossAppDomainDelegate(asmLoad.LoadAsm));
            return app;
        }
    }

编辑:

这里是一个更完整的示例,它显示了如何加载程序集并将信息传递回调用的应用程序域,还卸载了为加载程序集而创建的应用程序域。

Here is a more complete example, which shows how to load an assembly and pass information back to the calling app domain, and also unloads the app domain created to load the assembly.

class Program
{
    static void Main(string[] args)
    {
        var assemblyBytes = File.ReadAllBytes(@"C:\dev\Newtonsoft.Json.dll");

        // load an unload the same assembly 5 times
        for (int i = 0; i < 5; i++)
        {
            var assemblyContainer = AssemblyContainer.LoadAssembly(assemblyBytes, true);
            var assemblyName = assemblyContainer.AssemblyName;

            assemblyContainer.Unload();
        }

        Console.ReadKey();
    }
}    

[Serializable]
public class AssemblyContainer
{
    public byte[] AssemblyData { get; set; }
    public bool ReflectionOnly { get; set; }
    private AppDomain Container { get; set; }
    public AssemblyName AssemblyName { get; set; }

    /// <summary>
    /// Unload the domain containing the assembly
    /// </summary>
    public void Unload()
    {
        AppDomain.Unload(Container);
    }

    /// <summary>
    /// Load the assembly
    /// </summary>
    /// <remarks>This will be executed</remarks>
    public void LoadAssembly()
    {                
        var assembly = ReflectionOnly ? Assembly.ReflectionOnlyLoad(AssemblyData) : Assembly.Load(AssemblyData);
        AssemblyName = assembly.GetName();

        // set data to pick up from the main app domain
        Container.SetData("AssemblyData", AssemblyName);
    }

    /// <summary>
    /// Load the assembly into another domain
    /// </summary>
    /// <param name="assemblyBytes"></param>
    /// <param name="reflectionOnly"></param>
    /// <returns></returns>
    public static AssemblyContainer LoadAssembly(byte[] assemblyBytes, bool reflectionOnly = false)
    {
        var containerAppDomain = AppDomain.CreateDomain(
            "AssemblyContainer",
            AppDomain.CurrentDomain.Evidence,
            new AppDomainSetup
            {
                ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
            },
            new PermissionSet(PermissionState.Unrestricted));

        AssemblyContainer assemblyContainer = new AssemblyContainer()
        {
            AssemblyData = assemblyBytes,
            ReflectionOnly = reflectionOnly,
            Container = containerAppDomain
        };

        containerAppDomain.DoCallBack(new CrossAppDomainDelegate(assemblyContainer.LoadAssembly));

        // collect data from the other app domain
        assemblyContainer.AssemblyName = (AssemblyName)containerAppDomain.GetData("AssemblyData");
        return assemblyContainer;
    }            
}    

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

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