从插件调用时 LoadLibrary() 失败但在测试程序中有效

LoadLibrary() fails when called from plugin but works in test program

我正在开发 plugin for Autodesk 3ds Max 2017. As per Max's documentation,该插件是使用 VS 2015 工具集针对 10.0.10586.0 Windows SDK 在 VS 2017 中编译的。

当插件由 3ds Max 加载时,它会依次使用 LoadLibrary() 以编程方式加载大量 DLL。直到最近,这在我的机器上运行良好。它在其他开发人员的机器上也仍然可以正常工作。

现在我的机器上发生的事情是 LoadLibrary() 失败并且 returns 一个空句柄。错误码为127,即"The specified procedure could not be found."

我很确定我要加载的那个 DLL 所依赖的 DLL 在系统上可用。我已经对 Dependency Walker 及其现代版本 Dependencies.

进行了三重检查

事实上,Visual Studio 2017 中的以下程序 运行(也针对 10.0.10586.0 Windows SDK 使用 VS 2015 工具集)能够很好地加载该 DLL:

#include <Windows.h>

int main(int argc, char* argv[])
{
    auto result = LoadLibrary(L"C:\path\to\appleseed.dll");
}

为了进一步调查这个问题,我求助于 GFlags,它是 Windows 10.

调试工具的一部分

这是调用 LoadLibrary() 时发出的完整调试器输出:https://gist.github.com/dictoon/b3f9f7cb52d2d81078965133d5035a03

我相信(但我不是 100% 确定)此输出的相关错误如下:

5f4c:54bc @ 131346281 - LdrpReportError - ERROR: Locating export "StackWalkEx" for DLL "C:\Windows\SYSTEM32\dbgeng.dll" failed with status: 0xc0000139.
Exception thrown at 0x00007FFCC6A9EAA8 (ntdll.dll) in 3dsmax.exe: 0xC0000139: Entry Point Not Found.
5f4c:54bc @ 131346281 - LdrpGenericExceptionFilter - ERROR: Function LdrpSnapModule raised exception 0xc0000139
    Exception record: .exr 000000000223F030
    Context record: .cxr 000000000223EB40

dbgeng.dll 似乎是 Visual Studio 的调试器,所以我认为只有当 3ds Max 在 运行 中 运行 并附加了调试器时,错误才会发生但事实并非如此:当 3ds Max 自行启动时,DLL 也无法加载。

检查 C:\Windows\SYSTEM32\dbgeng.dll with Dependencies 显示 它确实导出了一个 StackWalkEx() 符号:

编辑 1:@RbMm 评论说 StackWalkEx() 实际上不是由 dbgeng.dll 导出,而是由 dbghelp.dll 导出,如下面的屏幕截图所示:

编辑 2:使用我尝试加载的 DLL 的发布版本,一切也都正常。查看调试器的输出,没有尝试加载 dbgeng.dll 或查找 StackWalkEx().

编辑 3:看来我要加载的库的调试版本 dbgeng.dll:

但是从头开始编写的小型测试 DLL 却没有!

编辑 4:我现在怀疑我们最近(从 Boost 1.55)切换到的 Boost 1.69(我试图加载的 DLL 依赖于它)引入了一个通过 Boost 1.65 中引入的 Stacktrace 库对 dbgeng.dll 的依赖。

问题是 3ds Max 附带的旧版本 dbghelp.dll 与 appleseed.dll 在调试构建期间链接的新版本冲突。

调用函数 StackWalkEx 失败,依赖于 dbghelp.dll StackWalkEx function

解决方案是停用或替换 Max 根目录中旧的、不兼容的 dbghelp.dll 版本。

StackWalkEx 是 DbgHelp 的一部分,由系统服务使用。它可能最近在 Windows 更新期间进行了更新,导致了重大更改。