ILMerge替代方案,如何在EXE文件中嵌入应用程序的相关DLL?

正如这里所说的,我试图在exe应用程序中嵌入dll以便只分发一个exe,但是当我尝试在安装了完整.NET 4的xp机器上运行我的应用程序时它只是崩溃而没有错误,我放置以下内容主方法的代码

[STAThread] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { String resourceName = "AssemblyLoadingAndReflection." + new AssemblyName(args.Name).Name + ".dll"; using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) { Byte[] assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); return Assembly.Load(assemblyData); } }; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new frmrPrincipal()); } 

我有一个名为dlls的文件夹,我放置

 Functions.Shared.dll Alex.UI.dll Alex.Controls.dll 

并将我的Build Action设置为“Embedded Resource”。

如果我删除那段代码并通过单击一次安装程序设置要包含的dll它工作正常。 顺便说一句使用.NET Framework 4完整配置文件和VS2010 SP1

当它试图jit Main()方法时,抖动变为kaboom。 AssemblyResolve尚未注册,鸡肉和鸡蛋问题。 您只能在Main中使用可用的类型,因此您必须远离frmrPrincipal。 使用一个小帮助方法可以解决这个问题,但现在你必须使用[MethodImpl]来抑制内联。 你也不允许ngen.exe完成它的工作。

 using System.Runtime.CompilerServices; ... [STAThread] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { // etc.. } AvoidJitterBombing(); } [MethodImpl(MethodImplOptions.NoInlining)] private static void AvoidJitterBombing() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new frmrPrincipal()); } 

我最近玩这个,从这个或非常类似的代码开始,我认为resourceName的构造是错误的。 尝试在resolve方法的开头放置一个断点,然后在执行的程序集上调用GetManifestResourceNames()以查看它实际为您的嵌入式资源提供的名称。

我怀疑它可能是“dlls.Functions.Shared”等等而不是“AssemblyLoadingAndReflection.Functions.Shared”

您可以查看.NETZ ,我们将其与ClickOnce一起用于WinForms应用程序部署。

我怀疑你正试图用非托管代码加载一个DLL。 对于托管dll,只需在内存中读取和加载程序集即可,或者您可以从某个位置加载,甚至无需读取。 对于混合模式程序集,我只能通过将字节写入文件并从其位置加载来获得成功。

 class Program { [STAThread] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { string assemblyName = new AssemblyName(args.Name).Name; if (assemblyName.EndsWith(".resources")) return null; string dllName = assemblyName + ".dll"; string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName); using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName)) { byte[] data = new byte[stream.Length]; s.Read(data, 0, data.Length); //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length); File.WriteAllBytes(dllFullPath, data); } return Assembly.LoadFrom(dllFullPath); }; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new frmrPrincipal()); } } 

其中Program是类名。 为了避免鸡和蛋的问题,您必须确保在访问程序集之前声明处理程序,并且不要在加载(程序集解析)部分中访问程序集成员(或实例化必须处理程序集的任何内容)。 另外要注意确保GetMyApplicationSpecificPath()不是任何临时目录,因为临时文件可能会被其他程序或自己删除(并不是在程序访问dll时它会被删除,但至少它是一个麻烦。 AppData位置很好)。 还要注意,你必须每次都写入字节,你不能只是从位置加载’因为dll已经驻留在那里。