我正在尝试使用以下代码在运行时加载dll库,这样我就不必为用户提供大量的dll文件以及主要的可执行文件。我已将所有dll文件作为嵌入资源包含在内,并且在参考部分中我已将其包括在内并将 CopyLocal 属性设置为false。但这里的问题是:1。所有的DLL都被复制到Bin \ Debug文件夹
2。我收到 FileNotFoundException 。
我做了很多搜索以解决这些问题,最后我就在这里。我得到了类似的代码here,但仍然无法做任何事情。我应该怎么做才能防止这种异常......?
是否有更好的方法为 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<string, Assembly> 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 项目的学生,我的论文将被提交。
答案 0 :(得分:1)
如果仍然是必须执行此操作的情况,则使用此OnResolveAssembly方法。如果您不想,则无需将它们预加载到数组中。这将在第一次实际需要时加载它们。
然后只是:
在文件属性中将其标记为资源。
// 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/
答案 1 :(得分:0)
尝试以下方法:
AppDomain.Current.BaseDirectory
上的文件已经存在,则继续使用下一个资源AppDomain.Current.BaseDirectory
。在try-catch中执行此操作,如果失败,请通知用户。要成功完成此步骤,您需要在安装文件夹(通常是“Program Files”的子文件夹)上进行写访问。这将通过以管理员身份运行程序来解决,这是第一次只有文件系统上写入文件。string
或AssemblyName
作为参数的Assembly.Load之一自行加载每个装配。