将dll库从Resource加载到当前域(在主exe文件中嵌入dll)

我正在尝试使用以下代码在运行时加载dll库,这样我就不必为用户提供大量的dll文件以及主要的可执行文件。 我已将所有dll文件作为嵌入式资源包含在内,并且在我已包含它们的参考部分中,并将CopyLocal属性设置为false。 但这里的问题是:
1.所有dll都被复制到Bin \ Debug文件夹
2.我收到了FileNotFoundException
我做了很多搜索以解决这些问题,最后我就在这里。 我在这里得到了类似的代码,但仍然无法做任何事情。 我应该怎么做才能防止这种exception……? 是否有更好的方法为Windows窗体应用程序(不是WPF)做同样的事情…… ??

using System; using System.Linq; using System.Windows.Forms; using System.Diagnostics; using System.Reflection; using System.Collections.Generic; using System.IO; namespace MyNameSpace { static class Program { static int cnt; static IDictionary assemblyDictionary; [STAThread] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; if (cnt != 1) { cnt = 1; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string[] resources = executingAssembly.GetManifestResourceNames(); foreach (string resource in resources) { if (resource.EndsWith(".dll")) { using (Stream stream = executingAssembly.GetManifestResourceStream(resource)) { if (stream == null) continue; byte[] assemblyRawBytes = new byte[stream.Length]; stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length); try { assemblyDictionary.Add(resource, Assembly.Load(assemblyRawBytes)); } catch (Exception ex) { MessageBox.Show("Failed to load: " + resource + " Exception: " + ex.Message); } } } } Program.Main(); } if (cnt == 1) { cnt = 2; System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest; Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); Application.ApplicationExit += new EventHandler(Application_ApplicationExit); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) { AssemblyName assemblyName = new AssemblyName(args.Name); string path = assemblyName.Name + ".dll"; if (assemblyDictionary.ContainsKey(path)) { return assemblyDictionary[path]; } return null; } } } 

如果我在我的代码中使用了不必要的东西,那么你可以告诉我正确的方法……我是一名学习Windows Form Application v4.0项目的学生,我的论文将被提交。

如果仍然必须执行此操作,则使用此OnResolveAssembly方法。 如果您不想,则无需将它们预加载到数组中。 这将在第一次实际需要时加载它们。

然后就是:

  • some.assembly.dll文件添加到项目中。
    • 可能不是对项目输出的引用
    • 但该文件是DLL项目的结果。
  • 将其标记为文件属性中的资源

     // This function is not called if the Assembly is already previously loaded into memory. // This function is not called if the Assembly is already in the same folder as the app. // private static Assembly OnResolveAssembly(object sender, ResolveEventArgs e) { var thisAssembly = Assembly.GetExecutingAssembly(); // Get the Name of the AssemblyFile var assemblyName = new AssemblyName(e.Name); var dllName = assemblyName.Name + ".dll"; // Load from Embedded Resources var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(dllName)); if (resources.Any()) { // 99% of cases will only have one matching item, but if you don't, // you will have to change the logic to handle those cases. var resourceName = resources.First(); using (var stream = thisAssembly.GetManifestResourceStream(resourceName)) { if (stream == null) return null; var block = new byte[stream.Length]; // Safely try to load the assembly. try { stream.Read(block, 0, block.Length); return Assembly.Load(block); } catch (IOException) { return null; } catch (BadImageFormatException) { return null; } } } // in the case the resource doesn't exist, return null. return null; } 

-Jesse

PS:来自http://www.paulrohde.com/merging-a-wpf-application-into-a-single-exe/

请尝试以下方法:

  • 对于每个.dll资源:
    • 如果该文件已经存在于AppDomain.Current.BaseDirectory上,则继续执行下一个资源
    • 否则将资源保存到AppDomain.Current.BaseDirectory 。 在try-catch中执行此操作,如果失败,请通知用户。 要成功完成此步骤,您需要在安装文件夹(通常是“Program Files”的子文件夹)上进行写访问。 这将通过以第一次仅在文件系统上写入文件的方式以管理员身份运行程序来解决。
  • 如果您的VS项目引用了程序集,那么您不必自己加载它们。 要理解为什么这项工作需要了解CLR如何定位assembly 。
  • 否则,您需要使用其中一个以stringAssemblyName作为参数的Assembly.Load自己加载每个程序集。