【问题标题】:Loading a .NET DLL from Resources inside a Win32/clr DLL从 Win32/clr DLL 中的资源加载 .NET DLL
【发布时间】:2014-05-04 01:46:15
【问题描述】:

我编写了一个 Win32-DLL(在 VS 2010/13 中支持 clr,c++)作为另一个/旧 VB6 应用程序的扩展,并使用 opensource-dll PDFSharp。

它工作正常,但是如果从目录中删除“PDFSharp.dll”,如果程序尝试加载我的 dll,应用程序就会崩溃。 我想将 Sharp DLL 包含到我的 DLL 中,因此只需要一个 DLL。 我尝试将其添加到资源中,并在运行时通过

加载/捕获错误
AppDomain^ root = AppDomain::CurrentDomain;

root->CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(MyResolveEventHandler);

在应用程序调用的第一个函数中,但我的问题是,应用程序/dll 在我处理某些事情之前就崩溃了。

ILMerge 无能为力,因为它是 Win32/net(clr) DLL 而不是 100% NET-DLL。

【问题讨论】:

  • C# 引用混合模式 DLL,还是混合模式 DLL 引用 C# 程序集?您可以使用 C# 编译器生成 .netmodule,C++/CLI link.exe 会很高兴地将其与混合模式 C++/CLI 代码合并。
  • 嗨,你的回答。有没有创建 .netmodule 文件的好方法?每个 .cs 文件(超过 50 个)的 csc.exe /t:module 有点长,但我在 vs (c#) 中找不到特殊的编译器选项
  • 一些研究表明,Visual Studio 构建系统 MSBUILD 支持构建 .netmodule 文件。但是没有 UI 来配置它,您必须在文本编辑器中编辑 .vcxproj 并将 <OutputType> 设置更改为 module
  • 非常感谢,效果很好!创建.netmodule,然后将“#using ”添加到cpp项目,删除对PDFSharp.dll的引用并在c++命令行中添加“/link PDFSharp.netmodule /LTCG”!
  • 好的,我会写一个答案来解释这种方法。

标签: c# .net dll c++-cli


【解决方案1】:

C++/CLI 混合模式 DLL 有两组引用:PE 标头中的本地导入和 .NET 程序集引用。查找本地导入的问题会导致您观察到的症状,即加载程序集在加载过程中早期失败并且无法被拦截和恢复。

我不清楚为什么本地依赖规则在这里适用。对于需要使用您控制的备用搜索顺序来定位的真正本机依赖项,​​可以应用延迟加载。但这不能与引用的 .NET 程序集一起使用。

无论如何,最简单的解决方法是根本不需要单独的程序集。您的目标是单文件部署,理想的单文件部署方案是所有代码都包含在一个 DLL 中,并且您不需要在运行时解压缩第二个文件。

对于纯 .NET 程序集,有一个 ILMerge 工具可以将多个 DLL 组合到一个文件中。但是您的案例有一个 C++/CLI 混合模式 DLL,而不是纯 MSIL。

在本机程序中使用多种语言通常会有所不同。本机代码不是从每个工具集生成完整的可执行文件,而是标准化所有各种工具集都知道如何生成的目标文件格式(Windows .obj,Linux .o),然后链接步骤可以将来自多种语言。目标文件通常捆绑到静态库中。 (静态库只是对象文件的存档,带有符号索引)因为 C++/CLI 工具集是基于原生 C++ 设计的,所以它也使用这个模型。

这种与语言无关的“目标文件”的 .NET 版本可以进一步链接,它是一个.netmodule 文件。在内部,它是一个没有清单的 .NET 程序集。在功能上,它就像一个静态库。并且 C++/CLI link.exe 可以将 C#(和 VB 和 F# 等).netmodule 静态库与 C++/CLI 目标文件和静态库以及本机目标文件和库链接在一起,当它创建混合-模式组装。

这不是最直接的过程,因为虽然底层工具链支持它,但 Visual Studio 项目选项对话框没有用于创建或使用 .netmodule 静态库的 UI。

要让 C# 端生成.netmodule,您应该打开.csproj 文件并将<OutputType> 设置更改为module。然后在 Visual Studio 中重新打开项目并照常构建。

在 C++/CLI 方面,项目选项对话框允许您自定义编译和链接命令行。更改链接器命令以包含 /link 和 .netmodule 文件的名称。

如果操作正确,C++/CLI 链接器将创建一个混合模式 DLL,其中包含来自 C# 和 C++/CLI 源文件的所有类型和代码。并且 C# 和 C++/CLI 之间的所有内部使用都已经解决,因此您不必担心在运行时缺少依赖项。好吧,至少不是这些依赖;您未选择链接的任何内容仍将正常处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多