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

C++/CLI application error after IlMerge

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

IlMerge 输出:

ilmerge /log /out:test1.exe test.exe
ILMerge version 2.12.803.0
Copyright (C) Microsoft Corporation 2004-2006. All rights reserved.
ILMerge /log /out:test1.exe test.exe
Set platform to 'v2', using directory 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727' for mscorlib.dll
Running on Microsoft (R) .NET Framework v2.0.50727
mscorlib.dll version = 2.0.0.0
The list of input assemblies is:
        test.exe
Trying to read assembly from the file 'test.exe'.
        Successfully read in assembly.
        There were no errors reported in test's metadata.
Checking to see that all of the input assemblies have a compatible PeKind.
        test.PeKind = ILonly, Requires32bits
All input assemblies have a compatible PeKind value.
Using assembly 'test' for assembly-level attributes for the target assembly.
Merging assembly 'test' into target assembly.
Copying 4 Win32 Resources from assembly 'test' into target assembly.
Transferring entry point '.mainCRTStartupStrArray(System.String[])' from assembly 'test' to assembly 'test1'.
        There were no errors reported in the target assembly's metadata.
ILMerge: Writing target assembly 'test1.exe'.
AssemblyResolver: Assembly 'test' is referencing assembly 'Microsoft.VisualC'.
        AssemblyResolver: Attempting referencing assembly's directory.
        AssemblyResolver: Did not find the assembly in referencing assembly's directory.
        AssemblyResolver: Attempting input directory.
        AssemblyResolver: Did not find the assembly in the input directory.
        AssemblyResolver: Attempting user-supplied directories.
        AssemblyResolver: No user-supplied directories.
        AssemblyResolver: Attempting framework directory.
Can not find PDB file. Debug info will not be available for assembly 'Microsoft.VisualC'.
Resolved assembly reference 'Microsoft.VisualC' to 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\..\v2.0.50727\Microsoft.VisualC.dll'. (Used framework directory.)
Location for referenced module 'KERNEL32.dll' is ''
Location for referenced module 'MSVCR100.dll' is ''
Location for referenced assembly 'mscorlib' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll'
        There were no errors reported in mscorlib's metadata.
Location for referenced assembly 'System' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\system.dll'
        There were no errors reported in  System's metadata.
Location for referenced assembly 'Microsoft.VisualC' is 'C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.VisualC.dll'
        There were no errors reported in  Microsoft.VisualC's metadata.
ILMerge: Done.

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

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

Unhandled Exception: System.TypeInitializationException: The type initializer for '' threw an exception. ---> .ModuleLoadException: The C++ module failed to load during registration
 for the unload events.
 ---> System.TypeInitializationException: The type initializer for ".ModuleUninitializer" threw an exception. ---> System.MissingMethodException: Method not found: "Void System.Threading.Monitor.Enter(System.Object, Boolean ByRef)".
   in System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(Delegate d)
   in System.AppDomain.add_DomainUnload(EventHandler value)
   in .ModuleUninitializer..ctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 255
   in .ModuleUninitializer..cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 217
   --- End of inner exception stack trace ---
   in .RegisterModuleUninitializer(EventHandler handler) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 292
   in .LanguageSupport.InitializeUninitializer(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 426
   in .LanguageSupport._Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 545
   in .LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 697
   --- End of inner exception stack trace ---
   in .ThrowModuleLoadException(String errorMessage, Exception innerException) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 194
   in .LanguageSupport.Initialize(LanguageSupport* ) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 707
   in .cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 749
   --- End of inner exception stack trace ---

有什么想法吗?

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

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

The output file produced by the linker will be an assembly or a .netmodule with no run-time dependency on any of the .obj or .netmodules that were input to the linker.

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

似乎已找到解决方案。我使用 NuGet instead of 2.12.803 which is downloadable from Microsoft

使用了 ILMerge 的最新版本 2.14.1208