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

How to make LoadLibrary to show error dialog when there are missing dependencies

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

如果我们 运行 text.exe 在 Windows XP 上缺少 libfoo.dllLoadLibrary() 显示对话框警告而不是 libfoo.dll 实际上丢失并将 LastError 设置为 ERROR_MOD_NOT_FOUND (126)。

如果我们在 Windows 10 的相同条件下 运行 相同 text.exeLoadLibrary() 仅将 LastError 设置为 ERROR_MOD_NOT_FOUND,无对话框出现。

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

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

foo.c

int foo(int a, int b)
{
    return a + b;
}

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

bar.c

int foo(int a, int b);

int bar(int a, int b)
{
    return foo(a, b);
}

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

test.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;
}

编译:gcc test.c -o test

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

正如@DavidHeffernan 在对原始 post 的评论中指出的那样,应该在根本不同的层面上解决这个问题。由于 LoadLibrary() 的行为就像它应该的行为一样,关键是正确的安装和错误处理。

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

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