【问题标题】:LoadLibrary on OCX file fails in Windows 7 x64OCX 文件上的 LoadLibrary 在 Windows 7 x64 中失败
【发布时间】:2009-11-17 12:37:15
【问题描述】:

我需要从用旧版 C++ Builder 编写的旧版 Windows 应用程序中打开一个 html 帮助文件。 HtmlHelp 是通过 HtmlHelp.ocx 加载的,我是通过 LoadLibrary 加载的。

这多年来一直运行良好,但在 Windows 7 x64 中不再适用。在 Windows7 x86 下它也可能会失败,但我没有任何具有此操作系统的计算机,所以我目前无法尝试。

我正在动态加载 hhctrl.ocx,如下所示:

#define HHPathRegKey "CLSID\\{adb880a6-d8ff-11cf-9377-00aa003b7a11}\\InprocServer32"

bool THTMLHelper::LoadHtmlHelp()
{
  HKEY HHKey;
  DWORD PathSize = 255;
  char Path[255];
  bool R = false;

  if (::RegOpenKeyExA(HKEY_CLASSES_ROOT, HHPathRegKey, 0, KEY_QUERY_VALUE, (void **)&HHKey) == ERROR_SUCCESS)
  {
    if (::RegQueryValueExA(HHKey, "", NULL, NULL, (LPBYTE)Path, &PathSize) == ERROR_SUCCESS)
    {
      //*****************************************
      //LOADING FAILS HERE
      //PATH IS %SystemRoot%\System32\hhctrl.ocx          
      //*****************************************
      HHLibrary = ::LoadLibrary(Path);
      if (HHLibrary != 0)
      {
        __HtmlHelp = (HTML_HELP_PROC) ::GetProcAddress(HHLibrary, "HtmlHelpA");
        R = (__HtmlHelp != NULL);
        if (!R)
        {
          ::FreeLibrary(HHLibrary);
          HHLibrary = 0;
        }
      }
    }
    ::RegCloseKey(HHKey);
  }
  return R;
}

我检查了 Windows 7 系统上是否存在 %SystemRoot%\System32\hhctrl.ocx 并且确实存在。

为什么通过 LoadLibrary 加载它会失败?我该如何解决这个问题?

编辑: GetLastError 说(德语,所以我只是翻译):“找不到文件。”但我调试了函数,路径是“%SystemRoot%\System32\hhctrl.ocx”,文件确实存在。

另外,由于两个答案指向 64 位与 32 位问题的方向:我的应用程序是在 C++ Builder 5 中编译的 32 位可执行文件,因此如果我没记错的话,它应该是 32 位进程。还是我错误地假设?

【问题讨论】:

  • GetLastError 和 FileMon 说什么?
  • 好点。请参阅上面的第一个编辑。

标签: winapi windows-7 html-helper loadlibrary chm


【解决方案1】:

使用ExpandEnvironmentStrings 函数将%SystemRoot%\System32\hhctrl.ocx 扩展为用户安装的真实路径。 64 位操作系统将扩展路径正确重定向到 32 位 dll。

【讨论】:

    【解决方案2】:

    您不能在 64 位进程中加载​​ 32 位 dll,反之亦然。 ActiveX 控件当然是 Dll。

    您有时可以通过将 32 位 ActiveX 作为进程外服务器加载来解决此问题 - 然后根据需要将其托管在单独的 32 位(或 64 位)进程中。这要求 ActiveX 只使用系统已经知道如何编组的接口,和/或项目构建了 64 位和 32 位版本的代理存根 dll。


    Depends 是一个非常有用的工具,当您需要找出 Dll 无法加载的原因时。当然,作为 64 位操作系统上的 32 位应用程序,您需要知道 32 位应用程序不能访问 %SYSTEMROOT%\System32,并且也不能直接从 HKCR 读取和写入。 System32 实际上包含 64 位操作系统二进制文件,而 HKCR 包含 64 位应用程序的注册表项。

    名为“反射”的内核进程完全透明地将 32 位应用程序从 System32 重定向到 %SYSTEMROOT%\SysWow64。 同样,对HKEY_CLASSES_ROOT 的注册表访问被重定向到`HKEY_CLASSES_ROOT\Wow6432Node'。 你当然需要知道这一点,因为 explorer 和 regedit 是 64 位进程,会很高兴地向你展示 System32 和 HKCR 的 64 位内容。您需要明确导航到 32 位节点以仔细检查您的 32 位进程将获得的视图。

    【讨论】:

    • 我的应用程序是在 C++ Builder 5 中编译的 32 位可执行文件,所以如果我没记错的话,它应该是 32 位进程。还是我的假设是错误的?
    • 我必须承认,C++ Builder 5 将创建一个 32 位进程似乎非常引人注目。您通常必须相对努力地尝试创建和构建 64 位配置。在这种情况下,我在回复中添加了一些与在 64 位操作系统上诊断 32 位应用程序问题相关的信息。
    【解决方案3】:

    我现在在运行 W7 (x64) 时遇到完全相同的问题。

    当我将“%SystemRoot%\System32\hhctrl.ocx”更改为“c:\windows\System32\hhctrl.ocx”时,我让它工作了,但我想我需要弄清楚为什么 %SystemRoot% 会解析错了。

    顺便说一句:我正在 BCB2007 上构建一个 32 位应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多