使用Load-Time Dynamic Linking指定“备份”加载路径?

时间:2016-07-14 20:05:56

标签: windows winapi visual-c++

在Win32应用程序中使用“加载时动态链接”(在加载模块时使用加载dll的编译中使用导入库.lib)时,是否可能影响搜索顺序?

目标是使用正常搜索顺序加载库,如果在正常路径上找不到,则使用备用路径。

示例:foo.lib在项目中链接。在加载时:

  1. 如果系统路径或Dynamic-Link Library Search Order中提到的任何其他路径中存在foo.dll,则会加载它。

  2. 否则将加载mySpecifiedPath / foo.dll。

  3. 澄清:只有在标准LoadLibrary搜索路径中找不到dll版本时,才应加载备份dll。

2 个答案:

答案 0 :(得分:1)

将旧答案留在底部并在顶部添加一个新答案:

如上所述,延迟加载和延迟加载Failure Hook的组合提供了一种处理此问题的好方法。

在使用库中的任何符号之前注册加载备份dll的故障挂钩。

#include <Windows.h>
#include "foo.h"
#include <delayimp.h>

//access to set the failure hook
ExternC PfnDliHook   __pfnDliFailureHook2;

const char* dllName = "foo.dll";
const char* dllBackupPath = "pathToBackup\\foo.dll";
FARPROC WINAPI DelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
    //if the failure was failure to load the designated dll
    if (dliNotify == dliFailLoadLib &&
        strcmp(dllName, pdli->szDll) == 0 &&
        pdli->dwLastError == ERROR_MOD_NOT_FOUND)
    {
        printf("loading back-up dll\n");
        //return the successfully loaded back-up lib,
        //or 0, the LoadLibrary fails here
        HMODULE lib = LoadLibraryA(dllBackupPath);
        return (FARPROC)lib;
    }
    return 0;
}

int main()
{
    //set the Failure Hook
    __pfnDliFailureHook2 = &DelayLoadHook;

    //when this function is called the library will be loaded
    //from standard paths.  If it is not found the Failure Hook
    //set above will be called.
    int test = ::intReturningFuncFromFooDll();
    printf("%d", test);
    getchar();
    return 0;
}

===========下面的旧答案==============

看起来我正在寻找的是延迟加载,正如IInspectable的评论中提到的那样。我找到了相关信息:

Linker Support for Delay-Loaded DLLs

以下是一些代码,展示了我在原帖中提到的用法:

  //load the dll using the normal search
  HMODULE lib = LoadLibrary( L"foo.dll" );
  //if unsuccessful, try a specified path
  if (lib == NULL)
  {
    LoadLibrary( L"mySpecifiedPath/foo.dll" );
  }
  if (lib == NULL)
  {
    //make sure that the library is not used, 
    //or exit the application, as it was not found
  }

感谢您的帮助!

编辑旧回答:在使用库中的任何符号之前,将使用此动态加载。加载的延迟在第一次访问库中的符号时使用此处加载的模块填充符号地址。

答案 1 :(得分:0)

查看Dynamic-Link Library Search Order文档,显而易见的是,搜索到的最终位置是PATH环境变量。应用这些知识,满足您所有要求的最简单的解决方案是将备份位置附加到PATH变量。

这可以通过两种方式完成:

  1. 外部启动器:CreateProcess API调用允许应用程序通过 lpEnvironment 参数将自定义环境传递给新进程。可以通过调用GetEnvironmentStrings来查询当前进程的环境块。

  2. 使用/DELAYLOAD链接器选项启用所需DLL的延迟加载,并在应用程序启动时修改进程的环境。检索PATH环境变量(使用GetEnvironmentVariable)后,可以通过调用SetEnvironmentVariable在环境块中对其进行修改和更新。