C# 将程序集加载到applicationBase C的AppDomain外部站点#
所以最近我一直在做一个项目,在这个项目中,应用程序(或可执行文件,不管你怎么称呼它)需要能够加载和卸载在可执行文件文件夹中根本找不到的程序集。(甚至可能是另一个驱动器) 举个例子,我希望我的应用程序位于D:\AAA\theAppFolder,DLL文件的程序集位于C:\BBB\assemblies 仔细查看后,我发现AppDomain允许卸载自己和任何附加的程序集,因此我想尝试一下,但是经过几个小时的尝试后似乎出现了一个问题:AppDomains无法查看应用程序库之外的任何地方 根据AppDomain的纪录片(以及我自己的经验),您无法在ApplicationBase之外设置PrivateBinPath,如果我在应用程序所在的驱动器之外设置ApplicationBase(通过AppDomainSetup),我会得到System.IO.FileNotFoundException,抱怨它找不到应用程序本身 因此,我甚至无法达到使用AssemblyResolveEventHandler尝试使用MarhsalByRefObject继承类获取程序集的阶段 下面是一些与我当前尝试的内容相关的代码片段C# 将程序集加载到applicationBase C的AppDomain外部站点#,c#,.net-assembly,appdomain,marshalbyrefobject,C#,.net Assembly,Appdomain,Marshalbyrefobject,所以最近我一直在做一个项目,在这个项目中,应用程序(或可执行文件,不管你怎么称呼它)需要能够加载和卸载在可执行文件文件夹中根本找不到的程序集。(甚至可能是另一个驱动器) 举个例子,我希望我的应用程序位于D:\AAA\theAppFolder,DLL文件的程序集位于C:\BBB\assemblies 仔细查看后,我发现AppDomain允许卸载自己和任何附加的程序集,因此我想尝试一下,但是经过几个小时的尝试后似乎出现了一个问题:AppDomains无法查看应用程序库之外的任何地方 根据AppDom
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中,您的回答解释了我观察到的情况。我将类型(位于父域而非子域中)从父域传递到子域,然后它尝试从子域加载该类型,然后抛出“未找到文件”异常。你的回答节省了我的时间。谢谢帕诺斯!