C ++单元测试项目LoadLibrary失败,出现Ordinal Not Found错误

时间:2018-01-28 20:36:00

标签: c++ unit-testing mfc loadlibrary

我有一个C ++单元测试项目,我正在使用LoadLibraryEx函数来加载我为我的应用程序创建的dll,但LoadLibraryEx失败并返回NULL,之后我调用{{1函数和错误是182.我还注意到在执行GetLastError行后的输出窗口中出现错误LoadLibraryEx

请注意,当我运行应用程序时,库成功加载,加载仅在从单元测试加载时失败。

1 个答案:

答案 0 :(得分:1)

你的dll是来自 Comctl32.dll 的导入TaskDialogIndirect函数。但此功能仅由版本6 以及 Comctl32.dll 以后导出。但是对于使用,此版本必须是存在的活动激活上下文:

  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' 
        name='Microsoft.Windows.Common-Controls' 
        version='6.0.0.0' processorArchitecture='*'   
        publicKeyToken='6595b64144ccf1df' />
    </dependentAssembly>
  </dependency>

否则将加载 ComCtl32.dll 5.82 version,而不会导出TaskDialogIndirect并且dll无法加载。

哪个激活上下文在dll加载时有效?

如果dll有自己的清单(RT_MANIFESTISOLATIONAWARE_MANIFEST_RESOURCE_ID) - 将基于dll清单创建激活上下文,它将在dll加载期间使用。否则它未定义。这可以是(更快的)基于来自exe文件或其他文件的清单创建的上下文。

根据您的错误 - 我可以说 - 您的dll没有(RT_MANIFESTISOLATIONAWARE_MANIFEST_RESOURCE_ID)清单资源。这是错误。可能应用程序加载你的DLL有自己的清单,其中声明版本6的常见控件,因为结果DLL加载确定。但是单元测试exe根本没有清单,或清单中没有版本6。结果加载了旧版本的 comctl32.dll ,此处未导出TaskDialogIndirect

无论如何,dll必须不依赖于外部环境 - 它加载的位置。为此,强制性必须有自己的清单。

所以为dll创建清单,其中<dependency><dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' />并将此清单包含为资源:

ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST "manifest file name"

有了这个,当你将加载时 - 将始终使用 comctl32.dll 的版本6+

这样的研究错误怎么样?

在调用{之前“ ntdll.dll (在xp - DWORD LdrpDebugFlagsBOOLEAN ShowSnaps)到true之间设置0xFFFFFFBF的最有效方法{1}}在调试器中。因此,链接器在dll加载期间打印详细的调试消息 - 您可以准确查看进程失败的位置。另外,在某些困难的情况下,还要记录成功dll加载并比较这些日志。

  

序号 345 无法在动态链接库中找到    COMCTL32.DLL

当我们有序号而不是名字 - 运行

LoadLibrary

并查看日志。在日志中我们可以找到:

link.exe /dump /exports "<path>comctl32.lib" > comctl32.log

现在查看TaskDialogIndirect的msdn要求部分 - 当我们查看 Comctl32.dll 版本6 )时 - 一切都变得清晰了