3

我正在尝试使用以下代码在 C:\Windows\System32\ 文件夹中加载与打印机驱动程序一起安装的 DLL:

LoadLibraryW(L"C:\\Windows\\System32\\MagAPI.dll");

GetLastError()报告“找不到指定的模块”。如果我将 DLL 移到 System32 文件夹之外(例如 C:\SomeFolder\MagAPI.dll),那么它将加载正常,因此看起来这不是 DLL 本身的问题。是否有一些奇怪的 Windows 安全功能可能会阻止我的应用程序加载它?这是我唯一能想到的,但我找不到任何明确的答案。

这是 ShowSnaps 的调试输出,它显示了失败的位置:

1a8c:1fd4 @ 19006756 - LdrLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpLoadDll - INFO: Loading DLL C:\Windows\system32\MagAPI.dll from path C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpSearchPath - ENTER: DLL name: C:\Windows\system32\MagAPI.dll DLL path: C:\Windows\system32;C:\Windows\system;C:\Windows;.;<otherstuff>
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - ENTER: DLL name: C:\Windows\system32\MagAPI.dll
1a8c:1fd4 @ 19006756 - LdrpResolveFileName - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpSearchPath - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpFindOrMapDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrpLoadDll - RETURN: Status: 0xc0000135
1a8c:1fd4 @ 19006756 - LdrLoadDll - RETURN: Status: 0xc0000135
4

1 回答 1

6

由于您提到您的应用程序是 32 位的,因此您正在加载的 DLL 也必须是 32 位的。

失败的可能原因LoadLibrary()是您运行的是 64 位版本的 Windows,但您的打印机驱动程序错误地将其 32 位 DLL 安装到System32文件夹而不是SysWOW64文件夹中。

一些背景知识:在 64 位版本的 Windows 上,64 位 DLL 进入System32文件夹,32 位 DLL 进入SysWOW64文件夹。我知道这听起来应该是相反的,但不要让名字混淆你;出于向后兼容性的原因,这些文件夹的命名方式如此。该SysWOW64文件夹应该对应用程序是透明的:Windows 有一个称为文件系统重定向的功能,System32即使 DLL 是居然在里面SysWOW64

另一方面,LoadLibrary()只会拒绝加载放置在错误文件夹中的 DLL。这是您可能看到的行为。

您的问题的真正解决方案是联系打印机制造商并告知他们他们的驱动程序安装程序将其 DLL 放入了 64 位 Windows 版本下的错误文件夹中。如果他们修复了这个问题,您的应用程序将开始正常工作,而无需对现有代码进行任何更改。

同时,您应该能够通过执行以下操作来解决您的问题:

  1. 在尝试加载 DLL 之前,将 DLL 从%windir%\Sysnative您可以控制的某个已知文件夹中复制。(我建议您在其中创建一个唯一命名的文件夹%TEMP%并将 DLL 复制到该文件夹​​中)。注意:Sysnative是映射到本机系统文件夹的特殊别名,System32在 64 位版本的 Windows 下。
  2. 调用LoadLibrary()并传递您在步骤 1 中创建的 DLL 副本的路径。
  3. 使用完 DLL 后,将其卸载并删除您在步骤 1 中创建的副本。

如果您需要支持 64 位 Windows XP,上述解决方法可能不起作用,因为该Sysnative别名已记录为仅适用于 Windows Vista 或更高版本。另一种解决方法是手动绕过文件系统重定向:

  1. 通过调用临时禁用文件系统重定向Wow64DisableWow64FsRedirection()将允许您的应用程序查看System32.
  2. 将 DLL 复制System32到您可以控制的某个已知文件夹中。
  3. 通过调用重新启用文件系统重定向Wow64RevertWow64FsRedirection()
  4. 调用LoadLibrary()并传递您在步骤 2 中创建的 DLL 副本的路径。
  5. 使用完 DLL 后,将其卸载并删除您在步骤 2 中创建的副本。

请注意,如果您正在考虑调用Wow64DisableWow64FsRedirection()来开始LoadLibrary()工作而不必复制 DLL,请不要打扰:LoadLibrary()不要注意该设置。(我实际测试过。)

更多信息:文件系统重定向器

于 2013-08-31T23:11:34.587 回答