当前位置:主页 > 纯净版系统教程 >

win缺少dll文件如何查

发布时间:2018-01-08    作者:纯净版官网    来源:http://www.ku551.com

win缺少dll文件如何查

自从操作系统更新到64位以后,就要不断的需要面对32位、64位的问题。相信有许多人并不是很清楚32位程序与64位程序的区别,以及program Files (x86),program Files的区别。同时,对于程序的dll文件应该放到system32文件夹,还是syswow64,大部分人做的决定是,32位程序放到system32,64位程序放到syswow64。是不是这样呢,那么今天就由我身边发生的一个案例来全面的说明一下。

dll文件不匹配导致数据库无法启动

前段时间,数据库做了一些功能上的改进,于是用Vs2010编译检出了一个版本,供尝试部尝试。尝试部拿到数据库后,通过批解决将数据库程序,注册为服务。虽然执行的是批解决,实际上注册服务的过程,是通过运行数据库程序,并给其传入命令行参数来完成的,详情请看这篇文章玩转win服务系列——debug、Release版本的注册和卸载,及其原理。

通过批解决运行程序后,出现如下问题:

 

出现这种问题,尝试部不淡定了,叫我去看。我又试着运行了一下程序,依然出现这个问题。“可是在我的机器上运行的挺好的啊”,这是我说的第一句话,相信许多人看了这句话就会心的笑了。

有问题便是有问题,既然我的机器上可以正常运行,那么尝试机为何不行呢,首先要查找原因。

数据库是用Vs2010编译的,那么在其他机器上运行,就需要运行的操作系统中以及安装了Vs2010的运行时,否则就会因为缺少程序运行所必须的dll文件而无法正常运行。我想应该是这个原因,但又一想,如果没有装运行时的话,会提示缺少msvcr100.dll、msvcp100.dll等文件,上图中的问题显然不是缺少dll问题。问题有点复杂,为了容易,先试着安装运行时,看能不能处理吧。

将Vs2010的x86和x64 Runtime安装包全装了一遍。再运行程序,依然是这个醒目的错误。

虽然安装运行时没有处理这个问题,但根据经验判断,要么是缺少dll文件,要么便是dll文件版本出了问题。那么,接下来便是想方法证明这个猜想。

通过dependency walker检测数据库程序,所有依赖的dll文件都存在,没有发现什么问题。然后通过win sysinternals中的ListdLLs工具检测当前运行的进程已经加载的dll文件,从列表中看到msvcr100.dll没有加载,猜测便是这个dll文件出了问题。从我的机器上找到这个文件,替换了尝试机上的msvcr100.dll文件后,数据库就正常运行了。

原来,刚刚启动数据库的时候,提示找不到msvcr100.dll文件,尝试的同事就从其他的xp系统的机器上找了这个文件,并分别放入到system32和syswow64中,于是就导致了上图中的这个问题。

由于xp系统是32位的,所以找到的msvcr100.dll文件也是32位,当把这个32位程序放到system32文件夹后,启动64位数据库,就会加载这个32位dll,由于64位程序只能加载64位dll,所以当程序测试加载32位dll时,就会报错了。

究竟是system32还是syswow64

win10、server2008等64位系统出来以后,为了兼容32位程序,所以采用了wow64方案,在系统文件夹中,可以看到一个system32文件夹,和一个syswow64文件夹。虽然这个方案对于程序来说,可以很方便的兼容32位程序,但是对于一般用户来说,想分辨system32和syswow64那就有点困难了,因为名字太有迷惑性了。

至于微软为何采用wow64方案,我就不简介了,感兴致的伙伴可以看这篇文章:什么是syswow64。这篇文章全面的教程了wow64技术,以及64位系统兼容32位程序的处境。

最后,你们可以了解:

  • syswow64文件夹,是64位win,用来存放32位win系统文件的地方,而system32文件夹,是用来存放64位程序文件的地方。
  • 当32位程序加载system32文件夹中的dll时,操作系统会自动映射到syswow64文件夹中的对应的文件。

看到这些,您一定会认为您真正的明白了system32和syswow64的区别,我也一样,我以为我真的懂了,但是真的懂了吗,是真懂了吗?

无论怎样还是请您坚持看完。

区分dll文件32位64位的程序让我倍感迷惑

上面说到的数据库无法启动的这种处境,已经遇到了不止一次了。每次遇到这种问题,我都想能不能有个工具可以检查system32和syswow64文件夹中的dll程序是不是对应的64位和32位程序。据我所知只有dumpbin可以查看一个dll文件是32位还是64位,但它明显不是我想要的工具,因为每次只能查看一个文件。

好吧,自己动手,丰衣足食,既然没有这种工具,那就来写一个吧,好在判断dll文件是32位还是64位也不是很难。

win系统下,exe、dll文件都可以称为pE文件,他们有相同的文件格式,称为pE文件格式。

pE文件的第一个部分是iMAGE_dos_HEAdER,大小为64B,对于检查32位64位来说,有一个重要的成员e_lfanew,这个成员的值为iMAGE_nT_HEAdERs的偏移。

iMAGE_dos_HEAdER的定义如下:

typedef struct _iMAGE_dos_HEAdER
{//(注:最左边是文件头的偏移量。)
+0h  woRd e_magic         //Magic dos signature MZ(4dh 5Ah)         dos可执行文件标记
+2h  woRd e_cblp          //Bytes on last page of file  
+4h  woRd e_cp            //pages in file
+6h  woRd e_crlc          //Relocations
+8h  woRd e_cparhdr       //size of header in paragraphs
+0ah woRd e_minalloc      //Minimun extra paragraphs needs
+0ch woRd e_maxalloc      //Maximun extra paragraphs needs
+0eh woRd e_ss            //intial(relative)ss value                dos代码的初始化堆栈ss
+10h woRd e_sp            //intial sp value                         dos代码的初始化堆栈指针sp
+12h woRd e_csum          //Checksum
+14h woRd e_ip            //intial ip value                         dos代码的初始化指令入口[指针ip]
+16h woRd e_cs            //intial(relative)Cs value                dos代码的初始堆栈入口
+18h woRd e_lfarlc        //File Address of relocation table
+1ah woRd e_ovno          //overlay number
+1ch woRd e_res[4]        //Reserved words
+24h woRd e_oemid         //oEM identifier(for e_oeminfo)
+26h woRd e_oeminfo       //oEM information;e_oemid specific 
+29h woRd e_res2[10]      //Reserved words
+3ch dwoRd e_lfanew       //offset to start of pE header            指向pE文件头
} iMAGE_dos_HEAdER;

iMAGE_nT_HEAdERs的定义如下:

typedef struct _iMAGE_nT_HEAdERs 
{ 
+0h  dwoRd                     signature;
+4h  iMAGE_FiLE_HEAdER         FileHeader;
+18h iMAGE_opTionAL_HEAdER32   optionalHeader;
} iMAGE_nT_HEAdERs;

signature 字段:在一个有效的 pE 文件里,signature 字段被配置为00004550h,AsCii 码字符是“pE00”。标志这 pE 文件头的开始。“pE00” 字符串是 pE 文件头的开始,dos 头部的 e_lfanew 字段正是指向这里。

iMAGE_FiLE_HEAdER 结构定义:

typedef struct _iMAGE_FiLE_HEAdER 
{
+04h  woRd  Machine;                        // 运行平台
+06h  woRd  numberofsections;               // 文件的区块数目
+08h  dwoRd Timedatestamp;                  // 文件创建日期和时间
+0Ch  dwoRd pointerTosymbolTable;           // 指向符号表(主要用于调试)
+10h  dwoRd numberofsymbols;                // 符号表中符号个数(同上)
+14h  woRd  sizeofoptionalHeader;           // iMAGE_opTionAL_HEAdER32 结构大小
+16h  woRd  Characteristics;                // 文件属性
} iMAGE_FiLE_HEAdER;

其中Machine字段表示可执行文件的目标Cpu类型:

  • iMAGE_FiLE_MACHinE_i386         0x014c   x86
  • iMAGE_FiLE_MACHinE_iA64         0x0200   intel itanium
  • iMAGE_FiLE_MACHinE_AMd64        0x8664  x64

这样不是很直观,上张图来看一下:

 

有了这些,你们就可以通过程序来判断32位、64位了,代码如下:

public static bool ispE32(string path)
{
    Filestream file = File.openRead(path);
    //移动到e_lfanew的位置处
    stream.seek(0x40 - 4, seekorigin.Begin);
    byte[] buf = new byte[4];
    stream.Read(buf, 0, buf.Length);
    //根据e_lfanew的值计算出Machine的位置
    int pos = BitConverter.Toint32(buf,0) + 4;
    stream.seek(pos, seekorigin.Begin);
    buf = new byte[2];
    stream.Read(buf, 0, buf.Length);
    //得到Machine的值,0x14C为32位,0x8664为64位
    int16 machine = BitConverter.Toint16(buf, 0);
    if (machine == 0x14C)
    {
        return true;
    }
    else
    {
        return false;
    }
}

最核心的功能完成了,剩下的便是界面和遍历文件夹了,效果图:

 

根据检测后果和实际处境判断,检测后果没问题。那么就开始真正的检测吧,system32和syswow64。检测后果如下图:

 

从图中看出,system32、syswow64中检测出的所有的文件均为32位程序,根据常识也可以判断出,实际肯定不是这样的。一定是程序出了什么问题,那么即可用十六进制编辑器看一下两个文件是否一致吧。

再次判断究竟是system32还是syswow64——意想不到的坑

通过uE查看两个文件夹中的msvcr110d.dll确实都是32位程序,而且用Beyond Compare进行比较,两个文件也没有差异。用工具查看两个文件的Md5也是完全一致:

 

难道两个文件真的都是32位吗,我还是觉得不太或许。

接下来将system32和syswow64中的msvcr110d.dll分别移动到其他文件夹,这样system32和syswow64就没有这个dll文件了,然后运行一个32位的需要这个dll文件的程序peTest,提示找不到这个dll文件。分别将原来system32和syswow64中的msvcr110.dll拷贝到这个peTest所在的目录,运行程序。当使用syswow64中的msvcr110d.dll时,程序可以正常运行,说明这个文件确实是32位。当使用system32中的msvcr110d.dll时,程序无法正常运行,出现文章开始时提到的错误。为何通过Beyond Compare、uE、Md5检测为同样的dll文件,一个可以正常运行,另外一个就不可以呢。

再次思考这两句话:

  • syswow64文件夹,是64位win,用来存放32位win系统文件的地方,而system32文件夹,是用来存放64位程序文件的地方。
  • 当32位程序加载system32文件夹中的dll时,操作系统会自动映射到syswow64文件夹中的对应的文件。

32位程序加载system32文件夹中的dll文件,操作系统会自动映射到syswow64文件夹,也便是说64位程序,系统不会再做映射。

通过任务管理器查看uE、Beyond Compare和Md5三个进程具体为32位进程,即三个程序具体是32位。

至此你们可以重新理解“32位程序加载system32文件夹中的dll文件,操作系统会自动映射到syswow64文件夹”这句话,应该是“只要32位程序访问system32文件夹,无论是加载dll,还是读取文本信息,都会被映射到syswow64文件夹”。

这个理解对吗,你们来做一个实验验证一下。

找一个32位的文本编辑器notepad++(win10系统自带的是64位),在syswow64文件夹中新建一个1.txt的文件,打开编辑此文件,内容为syswow64。然后在打开文件对话框中的输入框中输入“C:winsystem321.txt”,打开文件,看到内容为syswow64,如图所示:

 

system32中没有创建1.txt文件,32位程序访问system32中的1.txt文件,被自动映射到syswow64文件夹中的1.txt文件,而如果用64位的notepad编辑器打开system32中的1.txt文件,就会提示找不到文件:

 

由此就可以验证猜想“只要32位程序访问system32文件夹,无论是加载dll,还是读取文本信息,都会被映射到syswow64文件夹”是正确的。

program Files (x86)与program Files

由system32与syswow64的处境,考虑到program Files (x86)与program Files是不是也是这种处境。当32位程序访问program Files目录时,会被自动映射到program Files (x86)目录?

还是通过1.txt的方式来验证,发现当32位程序访问program Files目录时,并没有被映射到program Files (x86)目录。

32位程序真的需要访问system32吗

经过了这么多验证,总算是了解32位程序无法访问system32,只有64位程序才能访问,由此认为,这是win的一个非常大的坑。但是仔细想想,32位程序真的需要访问system32吗。就用这个dll检测工具来说吧。

如果在64位系统上,32位程序无法访问system32,为了访问它,就需要编译为64位。而如果程序编译为64位,就无法在32位系统上运行,同时由于在32位系统上不需要检测32位、64位,所以只需要32位程序直接。这可真是一个矛盾的事情,难道必须编译两个程序,一个32位,一个64位,来适应不同的操作系统吗。如果是C++的话,那么答案是这样的,必须编译一个32位一个64位。而dotnet就不一样了,编译的时候选择“AnyCpu”,并且不选择“首选32位”(Vs2012中默认选中),编译后的程序,可以同时在32位和64位系统上运行,32位系统上是32位进程,64位系统上是64位进程,是不是很方便呢,这正是dotnet和AnyCpu的魅力所在。

至此,dll检测程序,不需要做任何代码修改,只需在编译的时候选择AnyCpu,并消除“首选32位”选项,直接正常检测system32、syswow64文件夹中的dll文件。

32位程序与64位程序的区别总结

至此,我想应该是真的明白了system32与syswow64的区别了吧,这个不大不小的坑,算是迈过去了,那么就来总结一下32位程序与64位程序的区别:

  • syswow64文件夹,是64位win,用来存放32位win系统文件的地方,而system32文件夹,是用来存放64位程序文件的地方。
  • .net程序以AnyCpu设置,并选择“首选32位”编译,会以32位的进程运行,此时就无法访问system32文件夹中的文件;如果没有选择“首选32位”,则会以64位的进程运行,这样就可以访问system32文件夹了。(Vs2012中,“首选32位”默认是选中的)。
  • 32位程序的寻址空间有限,最多达到4G,而64位程序的寻址空间可以达到TB级,想要使用大内存的话,就更新到64位吧,好在dotnet程序从32位更新到64位比较容易,不像C++那么麻烦。
  • 32位程序访问system32目录,会自动被映射到syswow64目录,而64位程序可以访问system32目录和syswow64目录。
  • 32位程序与64位程序有各自的注册表。
  • 32位与64位程序都可以访问program Files (x86)与program Files目录。
  • 众多区别可以参考:32-bit and 64-bit win: frequently asked questions。

工作与学习过程中会遇到许多坑,一不小心就会跌倒,但是从哪儿跌倒的就从哪儿爬起来,总结经验教训,以饱满的热情再次起航,胜利就在不远的前方。

------分隔线------
  • 相关系统
  • Win10纯净版系统下载
  • 栏目专题推荐
  • 纯净版系统推荐
  • 系统教程推荐

友情链接: