我写了一个 Win32-DLL (在VS 2010/13中使用clr支持,c ++)作为另一个/旧VB6应用程序的扩展,并使用opensource-dll PDFSharp。
它工作正常,但如果" PDFSharp.dll"从目录中删除如果程序尝试加载我的DLL,应用程序崩溃。 我想将Sharp DLL包含在我的中,因此只需要一个 DLL 。 我尝试将其添加到资源,并在运行时加载/捕获错误
AppDomain^ root = AppDomain::CurrentDomain;
root->CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(MyResolveEventHandler);
在应用程序调用的第一个函数中,但我的问题是,app / dll在我处理之前崩溃了。
ILMerge无法提供帮助,因为它是一个Win32 / net(clr)DLL而不是100%的NET-DLL。
答案 0 :(得分:2)
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链接器将使用C#和C ++ / CLI源文件中的所有类型和代码创建单个混合模式DLL。 C#和C ++ / CLI之间的所有内部用法都已经解决,因此您不必担心在运行时缺少依赖项。好吧,至少不是这些依赖项;任何你没有选择链接仍然会正常处理。