Windows下DLL查找顺序160614.docx

上传人:b****6 文档编号:8153067 上传时间:2023-01-29 格式:DOCX 页数:11 大小:257.67KB
下载 相关 举报
Windows下DLL查找顺序160614.docx_第1页
第1页 / 共11页
Windows下DLL查找顺序160614.docx_第2页
第2页 / 共11页
Windows下DLL查找顺序160614.docx_第3页
第3页 / 共11页
Windows下DLL查找顺序160614.docx_第4页
第4页 / 共11页
Windows下DLL查找顺序160614.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

Windows下DLL查找顺序160614.docx

《Windows下DLL查找顺序160614.docx》由会员分享,可在线阅读,更多相关《Windows下DLL查找顺序160614.docx(11页珍藏版)》请在冰豆网上搜索。

Windows下DLL查找顺序160614.docx

Windows下DLL查找顺序160614

Windows下

DLL查找顺序

Hanford

2014年06月06日

目录

第1章说明2

1.1查找顺序2

1.1.1检查DllCharacteristics字段3

1.1.2读取manifset资源3

1.1.3读取manifset文件4

1.1.4载入5

1.1.5私有程序集5

1.1.6常规DLL的查找顺序7

1.2禁用隔离7

1.2.1修改DllCharacteristics字段7

1.2.2修改manifset9

1.2.3修改msvcr*.dll11

第1章说明

1.1查找顺序

使用VC++2008创建一个Win32项目,如下图所示

图1.1

编译这个程序(Debug版),将得到Test.exe文件。

使用eXeScope打开Test.exe,可以发现Test.exe在运行时需要文件msvcr90d.dll。

如下图所示:

图1.2

运行Test.exe时,Windows需要找到msvcr90d.dll,并将其加载至内存,然后Test.exe才能正常运行。

下面对msvcr90d.dll的查找顺序进行简要说明。

注意:

如果操作系统比WindowsXP还陈旧,msvcr90d.dll的查找顺序请参考1.1.6节。

1.1.1检查DllCharacteristics字段

Windows首先检查Test.exe中DllCharacteristics字段的数值

可使用eXeScope查看DllCharacteristics字段的数值,如下图所示:

图1.3

根据上图可知:

DllCharacteristics=0x8140,因此:

(0x8140&IMAGE_DLLCHARACTERISTICS_NO_ISOLATION)==0

上面的宏IMAGE_DLLCHARACTERISTICS_NO_ISOLATION其实就是0x200,它表示一个二进制位。

这个二进制位为0/1表示使用/不使用隔离(isolation)。

Test.exe中DllCharacteristics的这个二进制位为零,表示使用隔离。

如果某个程序不使用隔离,请跳至1.1.6节。

1.1.2读取manifset资源

Test.exe使用隔离,所以Windows会检查Test.exe里有没有manifset资源(类型为24,编号为1)。

下图表示Test.exe里存在manifset资源。

图1.4

可使用记事本打开文件Test.exe.embed.manifest,查看manifset资源的内容。

如下图所示:

图1.5

1.1.3读取manifset文件

如果上一步未找到manifset资源,Windows会检查是否存在manifset文件。

Test.exe的manifset文件就是Test.exe.manifest,它与Test.exe应在同一目录内,否则Windows无法找到。

Test.exe.manifest的内容应该与Test.exe.embed.manifest的内容保持一致。

这样Windows才能顺利读取manifset信息。

1.1.4载入

经过上面两步,Windows读取了manifset信息后发现:

Test.exe需要程序集“Microsoft.VC90.DebugCRT”(参考上图)。

现在,Windows会到C:

\WINDOWS\WinSxS目录下查找这个程序集。

在Windows7的C:

\Windows\winsxs\Manifests目录下存在文件x86_policy.9.0.microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_61305e07e4f1bc01.manifest,其内容如下图所示:

图1.6

其重点为:

9.0.21022.8版本的程序集“Microsoft.VC90.DebugCRT”被重定向至版本9.0.30729.1。

Windows会加载目录C:

\Windows\winsxs\x86_microsoft.vc90.debugcrt_1fc8b3b9a1e18e3b_9.0.30729.1_none_bb1f6aa1308c35eb目录下的msvcr90d.dll。

注意:

在WindowsXP下,重定向文件为9.0.30729.1.policy,它位于C:

\WINDOWS\WinSxS\Policies\x86_policy.9.0.Microsoft.VC90.DebugCRT_1fc8b3b9a1e18e3b_x-ww_037be232

1.1.5私有程序集

如果Windows在C:

\WINDOWS\WinSxS里找不到合适版本的msvcr90d.dll,就会在Test.exe所在目录进行查找。

位于C:

\WINDOWS\WinSxS目录下的程序集属于共享程序集,能够被多个程序所共享。

位于Test.exe所在目录的程序集属于Test.exe的私有程序集。

私有程序集的搜索步骤大致为:

在Test.exe所在目录查找子目录Microsoft.VC90.DebugCRT,如果存在就会核对该目录内的文件Microsoft.VC90.DebugCRT.manifest。

如果与要求的msvcr90d.dll版本一致,就会载入该目录下的msvcr90d.dll。

使用私有程序集的具体操作如下:

将目录C:

\ProgramFiles(x86)\MicrosoftVisualStudio9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT复制到Test.exe所在目录(接下来用表示)。

记事本打开\Microsoft.VC90.DebugCRT\Microsoft.VC90.DebugCRT.manifest,将版本号修改为Test.exe需要的版本号,亦即下图的版本号需要与图1.5的版本号保持一致。

图1.7

如果Test.exe需要载入Func.dll,而后者也需要程序集“Microsoft.VC90.DebugCRT”,就可以把目录C:

\ProgramFiles(x86)\MicrosoftVisualStudio9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT复制到Func.dll所在目录(注意:

不是Test.exe所在的目录)。

如果Test.exe与Func.dll在同一目录内,而它们需要的程序集版本还不相同,那就比较麻烦了。

说明:

1、私有程序集的搜索步骤远比本文描述的复杂,详细信息请参考MSDN中的《AssemblySearchingSequence》,网址如下:

2、如果Windows在共享程序集和私有程序集里均未找到合适版本的msvcr90d.dll,就会终止程序并显示如下界面,即使msvcr90d.dll与Test.exe在同一目录下,Windows也不会载入。

图1.8

1.1.6常规DLL的查找顺序

根据图1.2可知,Test.exe运行时还需要USER32.dll、KERNEL32.dll。

这两个动态库不属于任何程序集,是常规的DLL文件。

加载它们时的查找顺序请参考MSDN中的《Dynamic-LinkLibrarySearchOrder》,网址如下:

1.2禁用隔离

根据上文描述可知:

C:

\WINDOWS\WinSxS目录下允许存放某个组件(如:

msvcr90d.dll)的多个版本,此即为“并列共享”(Side-by-sideAssemblySharing)。

它主要是为了解决“DLL地狱”问题的,但它带来的问题比解决的问题并不少:

VC++2005/2008编译生成的程序在用户的电脑上可能无法运行。

为了能够更方便的发布程序,接下来介绍几种禁用隔离的方法。

1.2.1修改DllCharacteristics字段

修改DllCharacteristics字段的思路就是让DllCharacteristics&0x200不等于零。

下面分两种情况进行说明:

一是没有源代码,只有执行程序(如:

Test.exe);二是有源代码。

没有源代码,只能修改Test.exe文件。

根据图1.3可知:

Test.exe的字段DllCharacteristics首地址为0x13E,数值为0x8140。

将0x8140改成(0x8140|0x200)=0x8340即可。

如下图所示,使用vc2008的OpenWith打开文件Test.exe

图1.9

选择二进制编辑器(BinaryEditor)。

图1.10

按下Ctrl+G,输入地址0x13E,单击“OK”按钮,即可定位到0x13E处。

当前的数值为0x8140(注意:

低位在前,高位在后,就是下图中的4081),将4081改为4083(即更改数值为0x8340),然后保存Test.exe。

图1.11

如果有源代码,只要修改一下配置重新编译一遍即可。

具体就是修改“AllowIsolation”为“Don'tallowside-by-sideisolation”,如下图所示:

图1.12

现在Test.exe运行时就不会被隔离了,不过此时运行它还是会出错。

这是msvcr90d.dll的缘故,下文将说明如何对msvcr90d.dll进行修改。

1.2.2修改manifset

只有Test.exe,没有源代码,且manifset在Test.exe.manifest文件时。

...删除即可,如下图所示:

图1.13

只有Test.exe,没有源代码,且manifset在Test.exe内部时。

用图1.10中的资源编辑器(ResourceEditor)打开Test.exe,删除...之间的内容(或者直接删除整个manifest)。

如下图所示。

图1.14

如果有源代码,只要修改一下配置重新编译一遍即可。

具体就是修改“GenerateManifest”为“No”,如下图所示:

图1.15

没有manifest指定程序集,Test.exe运行时就不会查找、加载程序集了,不过此时运行它还是会出错。

这是msvcr90d.dll的缘故,下文将说明如何对msvcr90d.dll进行修改。

1.2.3修改msvcr*.dll

使用VC++2005或VC++2008编译生成的程序,只要用到了msvcr80.dll、msvcr80d.dll、msvcr90.dll、msvcr90d.dll这四个文件中的任何一个,就必须启用隔离。

一旦隔离被禁用,运行时就会崩溃并出现如下错误提示:

图1.16

这是msvcr?

?

.dll造成的。

以下代码节选自C:

\ProgramFiles(x86)\MicrosoftVisualStudio9.0\VC\crt\src\crtlib.c

#ifdefined(_CRT_CHECK_MANIFEST)

if(!

_check_manifest(hDllHandle))

{

returnFALSE;

}

#endif/*defined(_CRT_CHECK_MANIFEST)*/

这段代码表示:

加载msvcr?

?

.dll时会调用_check_manifest,检查manifest信息。

如果_check_manifest返回FALSE,整个程序就会崩溃。

现在再看看函数_check_manifest的代码(同样节选自crtlib.c):

staticBOOL__cdecl_check_manifest(HMODULEhDllHandle)

{

pfnFindActCtxSectionStringW=(PFN_FINDAC)GetProcAddress(

hKernel32,"FindActCtxSectionStringW");

if(pfnFindActCtxSectionStringW==NULL)

{

returnTRUE;

}

}

根据上面的代码可知:

将字符串"FindActCtxSectionStringW"的首字符改成00H,则GetProcAddress就会返回NULL,_check_manifest就会返回TRUE。

因此,使用vc2008的二进制编辑器打开某个msvcr?

?

.dll。

找到FindActCtxSectionStringW后,将第一个字符F改成00H即可(也可全部改成00H)。

图1.17

经过步骤1.2.1或1.2.2,以及步骤1.2.3,再将改好后的msvcr?

?

.dll与Test.exe放在同一目录内,现在Test.exe即可载入同一目录下的msvcr?

?

.dll了,再也不用到共享程序集、私有程序集里去查找、加载了。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1