IlMerge 后的 C++/CLI 应用程序错误

Posted

技术标签:

【中文标题】IlMerge 后的 C++/CLI 应用程序错误【英文标题】:C++/CLI application error after IlMerge 【发布时间】:2016-06-24 13:29:11 【问题描述】:

我有一个简单的 C++/CLI 控制台应用程序,它启动另一个进程并读取它的 STDOUT 和 STDERR。它使用外部(第 3 方)库。我正在尝试将它们嵌入到 .exe 映像中,以制作独立的可执行文件以进行部署。

IlMerge 输出:

合并 /log /out:test1.exe test.exe ILMerge 版本 2.12.803.0 版权所有 (C) Microsoft Corporation 2004-2006。版权所有。 ILMerge /log /out:test1.exe test.exe 将平台设置为“v2”,使用目录“C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727”作为 mscorlib.dll 在 Microsoft (R) .NET Framework v2.0.50727 上运行 mscorlib.dll 版本 = 2.0.0.0 输入程序集的列表是: 测试程序 试图从文件“test.exe”中读取程序集。 在汇编中成功读取。 测试的元数据中没有报告错误。 检查所有输入程序集是否具有兼容的 PeKind。 test.PeKind = ILonly, Requires32bits 所有输入程序集都有一个兼容的 PeKind 值。 对目标程序集的程序集级属性使用程序集“测试”。 将程序集“测试”合并到目标程序集中。 将 4 个 Win32 资源从程序集“测试”复制到目标程序集。 将入口点“.mainCRTStartupStrArray(System.String[])”从程序集“test”转移到程序集“test1”。 目标程序集的元数据中没有报告错误。 ILMerge:编写目标程序集“test1.exe”。 AssemblyResolver:程序集“测试”正在引用程序集“Microsoft.VisualC”。 AssemblyResolver:尝试引用程序集的目录。 AssemblyResolver:在引用程序集的目录中未找到程序集。 AssemblyResolver:正在尝试输入目录。 AssemblyResolver:未在输入目录中找到程序集。 AssemblyResolver:尝试用户提供的目录。 AssemblyResolver:没有用户提供的目录。 AssemblyResolver:正在尝试框架目录。 找不到 PDB 文件。调试信息不​​适用于程序集“Microsoft.VisualC”。 将程序集引用“Microsoft.VisualC”解析为“C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727\Microsoft.VisualC.dll”。 (使用的框架目录。) 引用模块“KERNEL32.dll”的位置是“” 引用模块“MSVCR100.dll”的位置是“” 引用程序集“mscorlib”的位置是“C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll” mscorlib 的元数据中没有报告错误。 引用程序集“系统”的位置是“C:\Windows\Microsoft.NET\Framework64\v2.0.50727\system.dll” 系统的元数据中没有报告错误。 引用程序集“Microsoft.VisualC”的位置是“C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.VisualC.dll” Microsoft.VisualC 的元数据中没有报告错误。 ILMerge:完成。

有一点让我有点困惑 - Framework64 库的使用考虑到源应用程序的 x86 平台。

test1.exe 的启动导致控制台输出如下:

未处理的异常:System.TypeInitializationException:“”的类型初始化程序引发了异常。 ---> .ModuleLoadException: C++ 模块在注册时加载失败 对于卸载事件。 ---> System.TypeInitializationException:“.ModuleUninitializer”的类型初始化程序引发了异常。 ---> System.MissingMethodException:找不到方法:“Void System.Threading.Monitor.Enter(System.Object, Boolean ByRef)”。 在 System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(Delegate d) 在 System.AppDomain.add_DomainUnload(EventHandler 值) 在 f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 255 中的 .ModuleUninitializer..ctor() 在 .ModuleUninitializer..cctor() 中的 f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 217 --- 内部异常堆栈跟踪结束 --- 在 f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 292 中的 .RegisterModuleUninitializer(EventHandler 处理程序) 在 .LanguageSupport.InitializeUninitializer(LanguageSupport* ) 在 f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 426 在 .LanguageSupport._Initialize(LanguageSupport* ) 在 f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 545 在 .LanguageSupport.Initialize(LanguageSupport* ) 在 f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 697 --- 内部异常堆栈跟踪结束 --- 在 .ThrowModuleLoadException(String errorMessage, Exception innerException) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 194 在 .LanguageSupport.Initialize(LanguageSupport* ) 在 f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 707 在 .cctor() 中的 f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:749 行 --- 内部异常堆栈跟踪结束 ---

有什么想法吗?

【问题讨论】:

另外:我在嵌入第 3 方库后遇到了同样的问题,并尝试使用 IlMerge 仅“重组”.exe 映像。 不要使用ILMerge,使用AppDomain.CurrentDomain.AssemblyResolve and a embedded resoruce instead。 ILMerge 的作者 Mike Barnett 对这篇文章表示赞同,并表示如果他知道这个技巧,他一开始就不会写 ILMerge。使用Fody/Costura,您可以在构建过程中自动化它。 @Scott AssemblyResolve 的行为与 ILMerge 完全不同(考虑访问具有“内部”可访问性的成员只是一个示例) 【参考方案1】:

ILMerge 不能与 C++/CLI(混合模式)程序集一起使用,但是 C++ 链接器也能够通过 netmodule 链接进行合并。

与 C# 编译器在看到 netmodules 时创建多文件程序集不同,C++ 链接器将生成单个文件程序集。

链接器生成的输出文件将是程序集或 .net 模块,运行时不依赖于输入到链接器的任何 .obj 或 .net 模块。

那么诀窍是获取库的 .netmodule 版本。 DLL 应该包含 .netmodule 所需的所有内容,但我不确定是否存在任何转换工具。一些参考资料表明 ildasm+ilasm 是可行的方法,但这可能不支持转换混淆或混合模式的程序集。

【讨论】:

我使用纯 MSIL 公共语言运行时支持,可执行文件不应该混合 AFAIR。【参考方案2】:

似乎找到了解决方案。我使用NuGet 获取了ILMerge 的最新版本2.14.1208,而不是可从Microsoft 下载的2.12.803

【讨论】:

以上是关于IlMerge 后的 C++/CLI 应用程序错误的主要内容,如果未能解决你的问题,请参考以下文章

ILMerge合并多个DLL

ILMerge合并多个DLL

ilmerge 可以将c++的dll合并吗

ILMerge合并多个DLL

ILMerge合并多个DLL

ILMerge合并多个DLL (转)