如何阻止延迟加载的 DLL 引发 "missing from your computer" 系统错误?

How do I stop a delay-loaded DLL from throwing a "missing from your computer" system error?

我昨天在我的插件中设置了延迟加载:

#ifdef _WIN32
#pragma warning (disable : 4100)  /* Disable Unreferenced parameter warning */
#include <windows.h>
#include <delayimp.h>
#endif

...

// Configuration Properties / Linker / Input / Additional Dependencies: ./lib/libcurl.lib;./lib/libxml2.lib;./lib/iconv.lib;./lib/zlib1.lib;%(AdditionalDependencies)
// Configuration Properties / Linker / Input /Delay Loaded Dlls: libcurl;libxml2;iconv;zlib1;%(DelayLoadDLLs)

#include "curl.h"
#include "HTMLparser.h"
#include "xpath.h"

#ifdef _WIN32
#pragma comment(lib, "libcurl")
#pragma comment(lib, "iconv")
#pragma comment(lib, "libxml2")
#pragma comment(lib, "zlib1")
#endif

[1]

我在插件加载时初始化 DLL:

#ifdef _WIN32
    SetDllDirectory(L"./plugins/ts3websitepreview/");
    if (FAILED(__HrLoadAllImportsForDll("libcurl.dll"))) {
        ts3Functions.logMessage("Could not load curl.", LogLevel_ERROR, "Plugin", 0);
        return 1;
    }
    if (FAILED(__HrLoadAllImportsForDll("libxml2.dll"))) {
        ts3Functions.logMessage("Could not load libxml.", LogLevel_ERROR, "Plugin", 0);
        return 1;
    }
    if (FAILED(__HrLoadAllImportsForDll("zlib1.dll"))) {
        ts3Functions.logMessage("Could not load zlib1.", LogLevel_ERROR, "Plugin", 0);
        return 1;
    }
    if (FAILED(__HrLoadAllImportsForDll("iconv.dll"))) {
        ts3Functions.logMessage("Could not load iconv.", LogLevel_ERROR, "Plugin", 0);
        return 1;
    }
#endif

[2]

这是添加 pragma 语句后的构建日志:

1>------ Build started: Project: ts3websitepreview, Configuration: Debug Win32 ------
1>Build started 2016-06-15 06:35:23 PM.
1>InitializeBuildStatus:
1>  Creating "Debug\ts3websitepreview.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1>  plugin.c
1>ManifestResourceCompile:
1>  All outputs are up-to-date.
1>Link:
1>     Creating library .\ts3websitepreview.lib and object .\ts3websitepreview.exp
1>LINK : warning LNK4199: /DELAYLOAD:libcurl ignored; no imports found from libcurl
1>LINK : warning LNK4199: /DELAYLOAD:libxml2 ignored; no imports found from libxml2
1>LINK : warning LNK4199: /DELAYLOAD:iconv ignored; no imports found from iconv
1>LINK : warning LNK4199: /DELAYLOAD:zlib1 ignored; no imports found from zlib1
1>Manifest:
1>  All outputs are up-to-date.
1>LinkEmbedManifest:
1>  All outputs are up-to-date.
1>  ts3websitepreview.vcxproj -> .\ts3websitepreview.dll
1>FinalizeBuildStatus:
1>  Deleting file "Debug\ts3websitepreview.unsuccessfulbuild".
1>  Touching "Debug\ts3websitepreview.lastbuildstate".
1>
1>Build succeeded.
1>
1>Time Elapsed 00:00:01.60
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

立即更改为:

1>------ Build started: Project: ts3websitepreview, Configuration: Debug Win32 ------
1>Build started 2016-06-15 06:39:54 PM.
1>InitializeBuildStatus:
1>  Creating "Debug\ts3websitepreview.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1>  plugin.c
1>ManifestResourceCompile:
1>  All outputs are up-to-date.
1>Manifest:
1>  All outputs are up-to-date.
1>LinkEmbedManifest:
1>  All outputs are up-to-date.
1>  ts3websitepreview.vcxproj -> .\ts3websitepreview.dll
1>FinalizeBuildStatus:
1>  Deleting file "Debug\ts3websitepreview.unsuccessfulbuild".
1>  Touching "Debug\ts3websitepreview.lastbuildstate".
1>
1>Build succeeded.
1>
1>Time Elapsed 00:00:00.71
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

在使用 进行另一次构建后,代码没有更改

但是,它仍然在插件初始化之前尝试加载 DLL,给我一个:

ts3client_win32.exe - System Error
The program can't start because libcurl.dll is missing from your computer. Try reinstalling the program to fix this problem.

我使用了教程 here and here for delayed loading. I've also read the questions here, here, here, and here 但 none 已经解决了我的问题。

不要忘记包含 "*.dll" 扩展名。在链接器选项中,您必须指定以下内容:

libcurl.dll;libxml2.dll;zlib1.dll;iconv.dll;

如果您使用 #pragma comment(lib, "libcurl"),那么您不必在链接器选项中再次指定它。

SetDllDirectory(L"./plugins/ts3websitepreview/"); 应该足够了。你不需要 __HrLoadAllImportsForDll

如果你想提前调用DLL的DLL_PROCESS_ATTACH,那么使用LoadLibrary代替。