【问题标题】:GetModuleHandle and GetProcAddress when COMCTL32.DLL is loaded twice两次加载 COMCTL32.DLL 时的 GetModuleHandle 和 GetProcAddress
【发布时间】:2011-08-31 16:14:56
【问题描述】:

我在一个进程中运行,其中COMCTL32.DLL 被加载了两次,一次使用版本 5.82.7601.17514,一次使用版本 6.10.7601.17514。旧版本由程序链接的某个旧 DLL 加载,而另一个版本由较新的 DLL 加载。

如果我使用GetModuleHandle (L"COMCTL32.DLL"),我将无法控制解析的 DLL。

当我调用GetProcAddress 以访问例如TaskDialogIndirect 时,我得到一个空指针,这肯定是因为我得到了旧版DLL 的句柄。

那么,当两个 DLL 都被加载时,是否有一些方法可以获取地址,比如 TaskDialogIndirect

如果没有,我能否以某种方式确保进程加载 6.10 版本而不是 5.82,希望我们的旧版 DLL 可以与较新版本的 COMCTL32 一起正常工作?

【问题讨论】:

  • 一个可能的快速修复方法是在 Visual Studio 中使用 File + Open + File 打开 DLL 的副本并删除清单资源。
  • 最后,我们通过添加清单而不是删除清单来确保应用程序使用 2new" 外观来解决此问题。但是,新外观 (COMCTL32 v6) 存在一些兼容性问题。

标签: winapi dll loadlibrary comctl32


【解决方案1】:

我猜您必须使用GetProcAddress() 而不是隐式链接,因为您希望您的应用在任务对话框不可用的 XP 上运行。

我可以看到三个选项:

  1. 使用隐式链接,但使用 MS 工具链支持的延迟加载。我不能 100% 确定它会为您提供正确的 comctl32,但值得一试。
  2. 使用activation context API 确保在调用LoadLibrary() 时comctl32 v6 清单正在运行。请致电 LoadLibrary() 而不是 GetModuleHandle() 以确保您获得清单的魔力。
  3. 枚举进程中的所有模块并选择正确的comctl32版本。有一个comprehensive example of how to do this on MSDN

激活上下文方法是最简洁的解决方案,但激活上下文 API 可能很难进入。我个人使用它来确保 Excel COM 加载项链接到 comctl32 v6。

模块枚举方法实现起来很快,有点脏,但效果很好。

【讨论】:

  • 我们将尝试 (3),因为它似乎可以很好地替代我们的代码需要做的事情。我不知道 activation context API ,谢谢你也指点我。
  • 激活API终于不用了。我们能够修复遗留代码,使其链接到COMCTL32 v6。
  • 非常感谢大卫,这确实帮助解决了我们遇到的一个主要问题。打算写一篇关于它的报告。
猜你喜欢
  • 2014-02-12
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 2011-10-26
相关资源
最近更新 更多