Windows DLL搜索顺序

原文:http://m.blog.csdn.net/blog/SR0ad/8180019

Windows程序直接或间接通过LoadLibrary/LoadLibraryEx加载一个DLL时,Windows会按照一定的顺序去系统中搜索指定的DLL,这个顺序称之为DLL搜索顺序。

下面举例A.exe调用B.dll的情况:

一、系统环境影响

1.如果在LoadLibrary/LoadLibraryEx调用时B.dll被指定了路径而该路径下并不存在B.dll,LoadLibrary/LoadLibraryEx会直接失败。

2.如果B.dll这个模块已经存在于内存中,系统只作manifest检查和redirection检查,而不管指定的B.dll路径是否与内存中的B.dll一致,并且系统不会再试图搜索B.dll。

3.KnownDlls,注册表中的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs 登记了所谓KnownDlls的名称和它们的路径。如果B.dll存在于该键下,系统会加载该注册表项指定路径的B.dll,而不管它在LoadLibrary/LoadLiraryEx被指定的路径。

4.如果被加载的B.dll依赖于其他的DLL,这些被依赖的DLL会按照B.dll没有指定路径时的相同方式加载。(假如B.dll依赖于它相同目录下的DepDll.dll,搜索DepDll.dll时并不会从B.dll所在目录开始)


二、标准的DLL搜索顺序

不附加任何其他条件时,标准的DLL搜索顺序如下:

1.应用程序的加载目录:D:\SR0ad

2.当前目录(默认为程序加载目录,可以通过SetCurrentDirectory修改,通过GetCurrentDirectory获取)

3.系统目录(32位系统下通常是,C:\Windows\System32,可以通过GetSystemDirectory获取)

4.16位系统目录(忽略)

5.Windows目录(通常是,C:\Windows,可以通过GetWindowsDirectory获取)

6.PATH环境变量中列出的所有路径


三、DLL重定向

DLL重定向用来解决系统中存在并且同时需要同一个DLL的多个版本的问题。当系统中已经存在B.dll,而A需要自己的B.dll时,就要用到DLL重定向。

在应用程序安装目录下建立应用程序名+.local后缀的重定向文件D:\SR0ad\A.exe.local,B.dll必须安装在D:\SR0ad\目录下。

不管重定向文件A.exe.local的内容如何,使用LoadLibrary/LoadLibraryEx加载B.dll时,只要D:\SR0ad\B.dll存在,系统都会加载D:\SR0ad\B.dll,而不管LoadLibrary/LoadLibraryEx是否为它指定全路径。

如果A.exe.local是个目录,并且D:\SR0ad\A.exe.local\B.dll存在,系统则会加载D:\SR0ad\A.exe.local\B.dll,同样不管为LoadLibrary/LoadLibraryEx是否为它指定全路径。

PS:DLL重定向有两个例外,KnownDLLs不能被重定向;如果应用程序存在manifest,.local文件会被忽略。


参考文章:Dynamic-Link Library Search Order,http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx


下面通过一个例子,来测试一下Win7下,具体的搜索路径是什么。

#include <Windows.h>
#include <iostream>
using namespace std;

BOOL APIENTRY DllMain(HMODULE hModule, 
					  DWORD  ul_reason_for_call, 
					  LPVOID lpReserved)
{
	switch(ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	
		char szDllPath[MAX_PATH] = {0};
		GetModuleFileNameA(hModule, szDllPath, MAX_PATH);
		cout<<"DLL PATH:"<<szDllPath<<endl;
		break;
	}

	return TRUE;
}
dll会获得自身的路径并输出,然后将dll放在各各路径,之后运行exe,通过LoadLibrary("SR0adDLL.dll");加载便可看到dll处于什么路径下。

#include <Windows.h>
#include <iostream>
using namespace std;

int main()
{
	HMODULE hDll = LoadLibrary("SR0adDLL.dll");
	if (!hDll)
	{
		cout<<"SR0adDLL.dll Load Error\n"<<endl;
	}
	return 0;
}

分别在一下路径放了生成的dll文件,之后运行exe,显示那个dll路径,删除掉继续运行,直至找不到dll文件为止。

至此也算是验证了搜索路径,至于安全搜索模式,就当忽略吧。


更多参考:http://blog.csdn.net/magictong/article/details/6931520

海风月影:神奇的马甲dll

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值