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

时间:2013-10-10 10:56:44

标签: c# .net-assembly appdomain marshalbyrefobject

最近我一直致力于一个项目,其中应用程序(或可执行文件,无论你想要什么),需要能够加载和卸载在可执行文件夹中找不到的程序集 at所有。 (甚至可能是另一个驱动器)

为了举例,我希望能够将我的应用程序放在 D:\ AAA \ theAppFolder 中,并将DLL文件的程序集放在 C:\ BBB \组件

仔细观察,我发现 AppDomain 允许卸载自己和任何附加组件的能力,所以我想我会试一试,但几个小时后似乎有问题值得尝试:AppDomains无法在应用程序库之外的任何地方查找。

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

因为我甚至无法达到可以使用AssemblyResolve ResolveEventHandler尝试使用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加载不在应用程序基础文件夹中的程序集?

1 个答案:

答案 0 :(得分:6)

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

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

因此,一般情况下,您不应在Type之间传递AssemblyAppDomains个对象。

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

当然,要使您的应用程序使用在子AppDomain中加载的程序集,您必须创建MarshalByRefObject派生类,它们将成为AppDomains之间的访问点。