【发布时间】:2020-02-26 06:08:54
【问题描述】:
我需要为我的解决方案创建一个新的 AppDomain,以便我可以从它自己的 AppDomain 调用该方法。我的解决方案的所有依赖 .dll 文件都已使用 Fody/Costura 嵌入到 my.exe 中。我创建了一个Loader : MarshalByRefObject 类来调用我的方法,但是当我在运行时执行加载程序时,我得到一个异常:
无法加载文件或程序集 'my.Assembly, Version=19.1.7242.23931, Culture=neutral, PublicKeyToken=null' 或其依赖项之一。该系统找不到指定的文件。
代码正在我的 AppDomain.CurrentDomain.BaseDirectory 中查找 .dll 文件以通过加载程序执行我的方法,但它们不存在但嵌入在可执行文件中。有没有办法让我的新 AppDomain 了解已嵌入到我的可执行文件中的程序集,而无需从 BaseDirectory 加载它们?
我已经寻找将其他程序集加载到我的新 AppDomain 中的方法,但还没有找到方法。我还怀疑可能有 Fody/Costura API 可以做到这一点,但还没有找到适用于这种情况的任何东西。
internal class Loader : MarshalByRefObject
{
object CallInternal(string dll, string typename, string method, object[] parameters)
{
Assembly a = Assembly.LoadFile(dll);
Type t = a.GetType(typename);
MethodInfo m = t.GetMethod(method);
Console.WriteLine("Invoking " + m.Name);
return m.Invoke(null, parameters);
}
public static object Call(string dll, string typename, string method, params object[] parameters)
{
object result = null;
try
{
AppDomain newAppDomain = AppDomain.CreateDomain("myNewDomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
Loader ld = (Loader)newAppDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(Loader).FullName); //DLL file not found exception thrown from here
result = (Loader)ld.CallInternal(dll, typename, method, parameters);
AppDomain.Unload(newAppDomain);
}
catch (Exception ee)
{
Console.WriteLine("Exception Message [" + ee.Message + "]");
PDFUtil.Report.ErrSilent(ee);
}
return result;
}
}
我希望实例化我的 Loader 类,而无需在运行时从磁盘加载 .dll。使用 Fody/Costura 嵌入式 .dll 可以做到这一点吗?
【问题讨论】:
-
您正在加载的 dll 是否使用其他 dll?那些 dll 在基本目录中吗? Net 可执行文件在与可执行文件(而不是基本文件夹)相同的文件夹中查找其他 dll。为确保加载最新版本的可执行文件,请始终使用菜单添加其他 dll:添加现有项,然后浏览到编译可执行文件的位置。然后使用解决方案资源管理器打开参考文件夹并右键单击现有项目并复选框复制到可执行文件夹。
-
是的,包含我尝试调用的方法的类需要 3 个 .dll 文件。这 3 个程序集已加载到当前 AppDomain 中,但在我的新 AppDomain 中不可用。因此,当我将 CreateInstanceAndUnwrap() 与我的新 AppDomain 一起使用时,它会引发 FileNotFound 异常。我想因为它没有在我的新 AppDomain 中找到程序集,所以它会在基本文件夹中查找它。 CreateInstanceAndUnwrap() .
-
如果我将这些 .dll 放入基本文件夹,代码可以工作,因为它正在那里寻找 .dll,但它违背了嵌入 .dll 的目的,因为我将提供包含这些的更大的可执行文件.dlls(在当前 AppDomain 中),但还必须将三个 .dll 分别安装到基本目录中,以便 .exe 可以在运行时找到它们。我宁愿找到一种方法在运行时将程序集从原始 AppDomain 添加到我的新 AppDomain,而不必从磁盘加载它们,这样我就可以只提供一个 .exe 文件。有没有办法用 Fody/Costura 做到这一点?。
-
不确定。每次启动应用程序时都要下载吗?您要问的似乎是“在运行时将程序集从原始 AppDomain 添加到我的新 AppDomain”和“我只能提供一个 .exe 文件”的冲突。
-
在 .exe 中有当前的 AppDomain。我在同一个 .exe 中创建了第二个 AppDomain。因为它是一个新的 AppDomain,所以它没有原始 AppDomain 所具有的任何程序集。为了使用反射来调用我的方法,我需要新 AppDomain 中的一些依赖程序集。试图弄清楚如何加载它们而不必从硬盘驱动器加载 .dll。所有这些都发生在同一个.exe 中。
标签: c# dll appdomain fody-costura