c# - 将程序集加载到 applicationBase C# 之外的 AppDomain

标签 c# .net-assembly appdomain marshalbyrefobject

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

举个例子,我希望我的应用程序位于 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 加载不在应用程序的基本文件夹中的程序集?

最佳答案

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

您的方法不起作用的原因是您在 AppDomain 之间传递 Assembly 对象。当您调用任何 GetAssembly 方法时,程序集将加载到子 AppDomain 中,但当该方法返回时,主 AppDomain 也会尝试加载程序集。当然,程序集不会被解析,因为它不在主 AppDomains 的 base dirprivate pathsGAC 中。

所以一般来说,你不应该在 AppDomains 之间传递 TypeAssembly 对象。

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

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

关于c# - 将程序集加载到 applicationBase C# 之外的 AppDomain,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19293887/

相关文章:

c# - foreach 语句不能对类型为 'int' 的变量进行操作,因为 'int' 不包含 'GetEnumerator' 的公共(public)定义

c# - 如何从 C# 中的类型(只有没有版本或文化或 publickeyToken 的程序集名称)中获取程序集名称(非限定名称)

.net - 有没有办法在 .NET 程序集中设置 IsPreRelease?

c# - 如何在不访问应用程序目录的情况下将程序集从字节数组加载到非默认 AppDomain 中?

c# - .Net CLR 卸载与关闭?

c# - 在 AppDomain 之间共享数据

c# - SSL TcpClient C# .Net Compact Framework 1.0

c# - 每次执行 N 个线程的最佳实践是什么?

c# - 在类库中实例化 CaSTLe Windsor 容器时的最佳实践是什么?

c# - 读/写进程内存声明