我的VS2008解决方案中有一个项目生成了一个引用了包含C++/CLI和非托管C++的dll的C#可执行文件。我想将它们合并为一个单独的可执行文件,因为其中的C++ dll包含了我想要嵌入到主可执行文件中的安全代码。
由于这个dll包含了托管和非托管代码,所以我不能使用ILMerge。建议的解决方案似乎是使用link.exe将C#程序集与C++对象文件链接在一起。这就是我正在尝试做的事情。
我手动编辑了C#可执行文件的项目文件以生成netmodule。我添加了一个后期构建步骤来运行link.exe将C# netmodule和编译好的C++对象文件链接在一起,然后运行mt.exe合并两个项目创建的程序集清单。这一步成功运行了,但是可执行文件仍然包含对正常构建过程中生成的C++项目的dll中定义的C++类型的引用和使用。
然后我在C++ dll的项目设置中指定了/NOASSEMBLY,这样它也会生成一个netmodule。在C#项目中,我删除了对C++项目的引用,但是在解决方案中添加了一个项目依赖项。我手动编辑了C#项目文件以类似于:
<ItemGroup>
<AddModules Include="..\Debug\librarycode.netmodule" />
</ItemGroup>
即引用由C++项目生成的C++ netmodule。然而,现在我的后期构建事件中链接器步骤失败并显示:error LNK2027: unresolved module reference 'librarycode.netmodule'
fatal error LNK1311: 1 unresolved module references:
由于我没有链接到库文件的netmodule,而是链接到用于生成netmodule的C++对象文件,所以这是完全可以理解的。
因此,简而言之,我如何将一个C#可执行文件和C++对象文件合并成一个单独的程序集?我错过了什么?
迄今为止,我参考的来源(除了MSDN上的link.exe命令链接参考等)是以下两篇文章:
- http://blogs.msdn.com/texblog/archive/2007/04/05/linking-native-c-into-c-applications.aspx
- http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx 我有一个演示解决方案,展示了我目前的工作情况,如果有帮助的话。
非常感谢您提前的帮助。
更新1
我完全按照Steve Teixeira博客中的示例操作,并验证它是有效的。使用反编译器,我可以看到生成的可执行文件包含两个netmodule。C# netmodule包含对另一个没有名称的netmodule的引用?如果将程序集移动到新目录中,第二个netmodule将不再被引用(显然),但是可执行文件仍会运行,因为具有正确定义的类型存在于C# netmodule中。
请注意,原始的C# netmodule确实包含对C++ netmodule的命名引用,因此必须是链接器步骤删除了名称。
在我的示例项目中尝试遵循此示例时,我在我的后期构建链接器步骤中添加了/ASSEMBLYMODULE参数。链接器现在失败了。
LNK2022: metadata operation failed (80040427) : Public type 'MixedLanguageLibrary.Class1' is defined in multiple places in this assembly: 'MixedLanguageDemo.exe' and 'mixedlanguagelibrary.netmodule'
LINK : fatal error LNK1255: link failed because of metadata errors
我猜测是链接器的魔法删除了我所缺少的模块引用名称。
欢迎任何想法。
更新2
我已经将我的项目简化到最简单的情况,并试图从命令行编译它。以下批处理文件成功地构建了 Steve Teixeira 博客中的示例:
setlocal
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
if errorlevel 1 goto End
cl /c /MD nativecode.cpp
if errorlevel 1 goto End
cl /clr /LN /MD clrcode.cpp nativecode.obj
if errorlevel 1 goto End
csc /target:module /addmodule:clrcode.netmodule Program.cs
if errorlevel 1 goto End
link /LTCG /CLRIMAGETYPE:IJW /ENTRY:ConsoleApplication1.Program.Main /SUBSYSTEM:CONSOLE /ASSEMBLYMODULE:clrcode.netmodule /OUT:MixedApp.exe clrcode.obj nativecode.obj program.netmodule
:End
以下批处理文件无法构建我的示例代码,出现链接器错误LNK2022:setlocal
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
if errorlevel 1 goto End
cl /c /MD messageprovider.cpp
if errorlevel 1 goto End
cl /clr /LN /MD managedmessageprovider.cpp messageprovider.obj
if errorlevel 1 goto End
csc /target:module /addmodule:managedmessageprovider.netmodule Program.cs Form1.cs Form1.Designer.cs
if errorlevel 1 goto End
link /LTCG /CLRIMAGETYPE:IJW /ENTRY:MixedLanguageDemo.Program.Main /SUBSYSTEM:WINDOWS /ASSEMBLYMODULE:managedmessageprovider.netmodule /OUT:MixedLanguageDemo.exe managedmessageprovider.obj messageprovider.obj program.netmodule
:End
现在是找茬时间 :-(