Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将程序集加载到applicationBase C的AppDomain外部站点#_C#_.net Assembly_Appdomain_Marshalbyrefobject - Fatal编程技术网

C# 将程序集加载到applicationBase C的AppDomain外部站点#

C# 将程序集加载到applicationBase C的AppDomain外部站点#,c#,.net-assembly,appdomain,marshalbyrefobject,C#,.net Assembly,Appdomain,Marshalbyrefobject,所以最近我一直在做一个项目,在这个项目中,应用程序(或可执行文件,不管你怎么称呼它)需要能够加载和卸载在可执行文件文件夹中根本找不到的程序集。(甚至可能是另一个驱动器) 举个例子,我希望我的应用程序位于D:\AAA\theAppFolder,DLL文件的程序集位于C:\BBB\assemblies 仔细查看后,我发现AppDomain允许卸载自己和任何附加的程序集,因此我想尝试一下,但是经过几个小时的尝试后似乎出现了一个问题:AppDomains无法查看应用程序库之外的任何地方 根据AppDom

所以最近我一直在做一个项目,在这个项目中,应用程序(或可执行文件,不管你怎么称呼它)需要能够加载和卸载在可执行文件文件夹中根本找不到的程序集。(甚至可能是另一个驱动器)

举个例子,我希望我的应用程序位于D:\AAA\theAppFolder,DLL文件的程序集位于C:\BBB\assemblies

仔细查看后,我发现AppDomain允许卸载自己和任何附加的程序集,因此我想尝试一下,但是经过几个小时的尝试后似乎出现了一个问题:AppDomains无法查看应用程序库之外的任何地方

根据AppDomain的纪录片(以及我自己的经验),您无法在ApplicationBase之外设置PrivateBinPath,如果我在应用程序所在的驱动器之外设置ApplicationBase(通过AppDomainSetup),我会得到System.IO.FileNotFoundException,抱怨它找不到应用程序本身

因此,我甚至无法达到使用AssemblyResolveEventHandler尝试使用MarhsalByRefObject继承类获取程序集的阶段

下面是一些与我当前尝试的内容相关的代码片段

    internal class RemoteDomain : MarshalByRefObject
    {
        public override object InitializeLifetimeService() //there's apparently an error for marshalbyref objects where they get removed after a while without this
        {
            return null;
        }
        public Assembly GetAssembly(byte[] assembly)
        {
            try
            {
                return Assembly.Load(assembly);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }
        public Assembly GetAssembly(string filepath)
        {
            try
            {
                return Assembly.LoadFrom(filepath);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }
    }

    public static Assembly LoadAssembly(string modName, BinBuffer bb)
    {
        string assembly = pathDirTemp+"/"+modName+".dll";
        File.WriteAllBytes(assembly, bb.ReadBytes(bb.BytesLeft()));
        RemoteDomain loader = (RemoteDomain)modsDomain.CreateInstanceAndUnwrap(typeof(RemoteDomain).Assembly.FullName, typeof(RemoteDomain).FullName);
        return loader.GetAssembly(assembly);
    }

具体来说:有没有办法让不可加载的AppDomain加载不在应用程序基本文件夹中的程序集?

每个
AppDomain
都有自己的基本目录,并且完全不受主应用程序基本目录的约束(除非它是应用程序的主AppDomain)。因此,您可以使用AppDomains实现您想要的功能

您的方法不起作用的原因是您正在AppDomains之间传递程序集对象。当调用任何
GetAssembly
方法时,程序集将加载到子AppDomain中,但当该方法返回时,主AppDomain也将尝试加载程序集。当然,程序集不会被解析,因为它不在主AppDomains的基本目录、专用路径或GAC中

因此,一般来说,您不应该在
AppDomains
之间传递
Type
Assembly
对象

可以在中找到加载程序集而不将其泄漏到主AppDomain的简单方法


当然,要使应用程序与加载在子AppDomains中的程序集一起工作,您必须生成
MarshalByRefObject
派生类,这些类将成为您在AppDomains之间的访问点。

可能需要使用全局变量,因此如果使用全局变量解决问题,您可以为其声明只读全局变量例如:

public static string a = "Moosaie";
将其转换为

public static readonly a = "Moosaie";

无论如何,您不能将全局动态值变量用于CLR程序集。

如何创建
AppDomain
?我有多种方法可以解决这个问题,当前的方法是modsDomain=AppDomain.CreateDomain(“randomname”,null,new-AppDomainSetup(){PrivateBinPath=AssembliesFolderPath});我知道路径是有效的,因为Directory.CreateDirectory(在代码的另一部分中调用)创建的文件夹很好。使用Assembly.Load(byte[])会带来麻烦。通过将程序集存储在临时目录中,并将类型展开到主appdomain中,您的回答解释了我观察到的情况。我将类型(位于父域而非子域中)从父域传递到子域,然后它尝试从子域加载该类型,然后抛出“未找到文件”异常。你的回答节省了我的时间。谢谢帕诺斯!