缺少依赖项时如何使 LoadLibrary 显示错误对话框

Hen*_*uts 5 c dll winapi loadlibrary windows-10

假设我们有两个动态库libfoo.dlllibbar.dll,鉴于这libbar.dll取决于libfoo.dll。此外,我们编译一个可执行文件test.exe,加载我们libbar.dll使用的 WinAPI 函数LoadLibrary()

如果我们text.exe在 Windows XP 上运行missing libfoo.dll,则LoadLibrary()显示对话框警告而不是libfoo.dll实际丢失并设置LastErrorERROR_MOD_NOT_FOUND(126)。

如果我们text.exe在相同条件下在 Windows 10 上运行相同,LoadLibrary()设置LastErrorERROR_MOD_NOT_FOUNDonly,则不会出现对话框。

在这两种情况下ErrorMode都是 0。那么是否有可能在LoadLibrary()调用过程中捕获缺少依赖项的名称,或者至少,如何 LoadLibrary()在 Windows 10 上显示错误对话框?

这是一个示例代码(使用 MinGW):

foo.c

int foo(int a, int b)
{
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

编译: gcc foo.c -o libfoo.dll -fPIC -shared

酒吧

int foo(int a, int b);

int bar(int a, int b)
{
    return foo(a, b);
}
Run Code Online (Sandbox Code Playgroud)

编译: gcc bar.c -o libbar.dll -fPIC -shared -L. -lfoo

测试.c

#include <windows.h>
#include <stdio.h>

typedef int (*pfn)(int a, int b);

int main()
{
    SetErrorMode(0);

    HMODULE hmod = LoadLibrary("libbar.dll");

    if(!hmod)
    {
        fprintf(stderr, "error loading library %d\n", GetLastError());
        return 1;
    }

    pfn bar = (pfn)GetProcAddress(hmod, "bar");
    if(bar)
    {
        fprintf(stdout, "bar(3, 1) = %d\n", bar(3, 1));
    }
    else
    {
        fprintf(stderr, "can't load bar foonction\n");
    }

    FreeLibrary(hmod);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译: gcc test.c -o test

Hen*_*uts 1

目前看来对于所提出的问题还没有优雅的解决方案。

正如 @DavidHeffernan 在原始帖子的评论中指出的那样,应该在根本不同的层面上解决问题。正如LoadLibrary()其应有的行为一样,关键是正确的安装和错误处理。

但是,如果需要显式捕获动态加载库的缺失依赖项,则可以应用 @IInspectable 和 @eryksun 提供的技术:

  • 为将要动态加载的库启用延迟加载 DLL 。这种方法为每个依赖模块提供辅助回调,因此可以就地处理缺少的依赖项。这种方法的主要缺点是应该使用适当的链接器标志重新编译目标库;
  • 可以编写从应用程序转储调试字符串的帮助程序实用程序(有关详细信息,请参阅原始帖子的 @eryksun 评论)。缺点:除了需要编写额外的模块之外,它还包括一些注册表操作。