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

C 当缺少依赖项时,如何使LoadLibrary显示错误对话框,c,winapi,dll,windows-10,loadlibrary,C,Winapi,Dll,Windows 10,Loadlibrary,假设我们有两个动态库libfoo.dll和libbar.dll,假设libbar.dll依赖于libfoo.dll。此外,我们还编译了一个可执行文件test.exe,它使用WinAPI函数LoadLibrary()加载我们的libbar.dll 如果我们在Windows XP上运行text.exe时缺少libfoo.dll,LoadLibrary()会显示对话框警报,而不是libfoo.dll实际缺少,并将LastError设置为ERROR\u MOD\u NOT\u FOUND(126) 如果

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

如果我们在Windows XP上运行
text.exe
时缺少
libfoo.dll
LoadLibrary()
会显示对话框警报,而不是
libfoo.dll
实际缺少,并将
LastError
设置为
ERROR\u MOD\u NOT\u FOUND
(126)

如果我们在Windows 10上以相同的条件运行相同的
text.exe
LoadLibrary()
LastError
设置为
ERROR\u MOD\u NOT\u FOUND
仅显示对话框

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

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

富科 编译时使用:
gcc foo.c-o libfoo.dll-fPIC-shared

酒吧c 编译时使用:
gcc bar.c-o libbar.dll-fPIC-shared-L-lfoo

测试c
#包括
#包括
类型定义内部(*pfn)(内部a、内部b);
int main()
{
设置错误模式(0);
HMODULE hmod=LoadLibrary(“libbar.dll”);
如果(!hmod)
{
fprintf(stderr,“加载库%d时出错”,GetLastError());
返回1;
}
pfn bar=(pfn)GetProcAddress(hmod,“bar”);
如果(巴)
{
fprintf(标准输出,“条(3,1)=%d\n”,条(3,1));
}
其他的
{
fprintf(stderr,“无法加载条操作\n”);
}
免费图书馆;
返回0;
}

编译时使用:
gcc test.c-o test

目前,似乎对提出的问题没有优雅的解决方案

正如@DavidHeffernan在对原始帖子的评论中所指出的,这个问题应该在一个根本不同的层面上得到解决。由于
LoadLibrary()
的行为与应有的行为相同,关键在于正确的安装和错误处理

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

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

可能与加载库函数docu中的默认模式有关。要启用或禁用加载程序在加载DLL期间显示的错误消息,请使用SetErrorMode函数。如上所述,我的ErrorMode设置为0(test.c示例中的SetErrorMode(0)),这意味着(根据msdn文档)它应该显示所有对话框。为什么要这样做?如果依赖的dll加载失败,xp调用
NtRaiseHardError
。因此,您可以查看错误对话框和设置错误模式。但是win10不能调用
NtRaiseHardError
more。因此,无错误对话框和错误模式在此不起作用
int foo(int a, int b)
{
    return a + b;
}
int foo(int a, int b);

int bar(int a, int b)
{
    return foo(a, b);
}
#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;
}