通常情况下应用程序 exe 文件与加载的 dll 会安装在同一个目录,想要延时加载 dll 只需要在 VS 属性页-》链接器-》输入-》延迟加载的 DLL 中填入想要加载的 DLL,在 属性页-》链接器-》高级-》卸载延迟加载的 DLL 改为 是 即可。
当应用程序和 DLL,不在同一个目录下时,程序只会在应用程序当前目录搜索 DLL, 此时将会加载失败。为了正确加载 DLL, 需要在程序中将 DLL 的安装目录设置进来。
在我的项目中,windows 系统会启动 AUDIODG.exe 的应用,这个文件在 system32 目录,我们部署一个 audio process objiect (APO)给这个应用调用,以达到音效的处理,这个APO又会调用其他的dll,这些dll 以延迟加载方式加载。如果APO dll 与 APO 依赖的 dll 都安装在 system32 下,自然不会有问题。但是一旦更改了安装目录,就会导致找不到dll的目录。所以在APO 代码中设置dll的搜索路径即可,如下:
//获取 dll 的目录
HMODULE GetSelfModuleHandle()
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery(GetSelfModuleHandle, &mbi, sizeof(mbi)) != 0) ? (HMODULE)mbi.AllocationBase : NULL);
}
// 设置dll 的搜索目录
void SetDelayLoadDllPath()
{
char DllPath[MAX_PATH] = { 0 };
GetModuleFileNameA(GetSelfModuleHandle(), DllPath, _countof(DllPath));
std::string dllPath_str = std::string(DllPath);
std::string path = dllPath_str.substr(0, dllPath_str.rfind("\\"));
LOG_TRACE("UAPO", "LoadEngine: UAPO Path is %s", path.c_str());
std::wstring wPath(path.begin(), path.end());
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
| LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS);
AddDllDirectory(wPath.c_str());
}