25

我在使用 LoadLibrary() 时遇到问题,并且收到一个对我来说没有意义的错误:

   ::SetLastError(0);

   m_hDll = ::LoadLibrary(szName);

   if (m_hDll == NULL) // Failure to load the DLL.
   {
      DWORD err = GetLastError();
   }

错误是 127(“找不到指定的过程。”) 这对我调用 LoadLibrary() 没有任何意义。 我还没有调用 GetProcaddress()。

DLL(和应用程序)都使用 VS++ 2005 SP1 编译。

可能出了什么问题?

4

9 回答 9

36

让我们一步一步来:

  1. 错误消息表示找到了 dll,但缺少所需的功能。(抖动是正确的。)这意味着您拥有所需的 dll,但不是正确的版本。(Davefiddes 是对的,尽管问题可能出在任何 dll 上,而不仅仅是 Microsoft 运行时库。而且,至少对于重大更新,Microsoft 为其运行时库提供了不同的名称,因此在这种情况下它不会成为问题。)

  2. 这没有意义,因为没有从正在加载的 dll 请求任何函数。(亚当是对的。)

  3. 因此,预计丢失的函数不会在 LoadLibrary 命令显式加载的 dll 中找到,而是在同时隐式加载的依赖 dll 中找到,因为第一个 dll 需要它。(Zebrabox 很接近。)

  4. 依赖 dll 是通过导入库或 .lib 文件“静态”链接到被显式加载的库的 dll,包含在显式加载的 dll 的链接器步骤中。(我打赌你不知道“动态链接库”可以是“静态链接的”。好吧,现在你知道了。)

  5. 如果您在不同的文件夹中有同一个 dll 的多个版本,那么这也可能是搜索路径问题(正如 zebrabox 所暗示的)。Dll 路径搜索顺序本身就是一个复杂的主题:请参阅http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx。这取决于操作系统等。在可行的情况下,最安全的选择是将所有潜在的问题 dll 与您的 exe 放在同一个文件夹中。

  6. 依赖 dll 也可以有自己的依赖 dll,这会使这个问题很难解决。Depends 可能会有所帮助,但如果没有,请尝试 filemon。在您的错误消息之前成功读取的最后一个 dll 是错误版本。

于 2010-04-08T20:52:51.867 回答
16

Microsoft gflags工具将始终准确地告诉您哪些依赖项无法加载以及原因。

运行gflags -i your_application.exe +sls。之后在调试器下执行应用程序以捕获加载程序跟踪

gflags 是调试工具的一部分——你可以检查一下C:\Program Files (x86)\Windows Kits\10\Debuggers\x64你是否已经拥有它。您可以将该目录添加到您的路径中,或者只在 cmd.exe 中从该目录执行 gflags。

例如,在运行 gflags 后,在调用上放置一个断点::LoadLibrary(_T("foo"))并在 Visual Studio 输出窗口中查找加载程序错误时跳过它,例如

4b00:396c @ 479194074 - LdrpSnapThunk - ERROR: Procedure "?SetObject@vis_DollarMap@@QEAAXHPEAX@Z" could not be located in DLL "bar.dll"
First-chance exception at 0x0000000077307EF8 (ntdll.dll) in your_application.exe: 0xC0000139: Entry Point Not Found.
4b00:396c @ 479194074 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapIAT raised exception 0xc0000139
    Exception record: .exr 0000000000129070
    Context record: .cxr 0000000000128B80
4b00:396c @ 479194074 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Snapping the imports from DLL "C:\test\64Debug\foo.DLL" to DLL "C:\test\64Debug\bar.dll" failed with status 0xc0000139

这意味着在加载的过程中foo.dll,依赖项bar.dll被导入,并且bar.dll导入失败。

依赖项导入失败,因为?SetObject@vis_DollarMap@@QEAAXHPEAX@Z缺少该过程 - 您可以将其分解public: void __cdecl vis_DollarMap::SetObject(int,void * __ptr64) __ptr64.

您可能拥有错误版本的依赖项——也许您需要重建依赖项以使其保持最新。


之后运行gflags -i your_application.exe -sls以禁用加载程序跟踪。

于 2016-05-11T16:59:13.350 回答
4

错误消息意味着找到了适当的 DLL,但缺少所需的过程导出。你有正确的 DLL 版本吗?

您可以使用它dumpbin.exe来检查您的 DLL 导出的函数并检查拼写。

于 2009-06-27T17:04:09.133 回答
4

安装调试工具并运行gflags -i your_application.exe +sls. 之后在调试器下执行应用程序以捕获加载程序跟踪。

于 2011-08-19T08:41:57.240 回答
2

我的两个猜测
1. LoadLibrary 调用指定 DLL 的 DllMain(第一次尝试附加到进程时)。远射,但它在那里吗?
2. LoadLibrary 将加载指定的 DLL 及其所有依赖项。因此,如果 DLL 的依赖模块无法位于将导致加载失败的搜索路径中 - 您可以使用 depends.exe 进行检查 - 可在此处获得

于 2009-06-27T18:08:08.237 回答
2

Do you have a mismatch between the runtimes used for your app and the DLL?

A problem that's bitten me with VS 2005 in the past is that one part is built as a Release build and the other as a Debug build. These pull in different versions of the Microsoft runtime DLLs which are incompatible as you can only have one loaded in a given process.

I think the reason that you see Error 127 is because your DLL is looking for a function in the loaded runtime DLL which isn't there because it's the wrong runtime.

于 2009-06-27T17:50:54.083 回答
0

调用 LoadLibrary() 后,我得到了相同的错误代码。最后通过dependency walker发现模块(szName)的一些依赖项丢失了。

于 2011-03-18T12:14:39.583 回答
0

我建议使用Dependency Walker来找出缺少哪个方法或需要或缺少哪些 DLL。

于 2012-10-13T08:00:03.100 回答
0

好的,这是我的解决方案:我们有一个复杂的依赖系统,其中有两个同名的 DLL (即server.dll),但位于不同的路径上。

client.dll被加载时LOAD_WITH_ALTERED_SEARCH_PATH,windows 似乎无法确定server.dll应该在符号解析中使用哪一个(server.dll当然,两者都已成功加载)。

解决方案很简单:让加载的 dll 具有唯一的名称,即server-1.dllserver-2.dll.

于 2019-09-10T14:37:10.497 回答