国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

dll文件32位64位檢測(cè)工具以及Windows文件夾SysWow64的坑

2019-11-17 03:18:51
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

dll文件32位64位檢測(cè)工具以及Windows文件夾SysWow64的坑

自從操作系統(tǒng)升級(jí)到64位以后,就要不斷的需要面對(duì)32位、64位的問(wèn)題。相信有很多人并不是很清楚32位程序與64位程序的區(qū)別,以及PRogram Files (x86),Program Files的區(qū)別。同時(shí),對(duì)于程序的dll文件應(yīng)該放到System32文件夾,還是SysWow64,大部分人做的決定是,32位程序放到System32,64位程序放到SysWow64。是不是這樣呢,那么今天就由我身邊發(fā)生的一個(gè)案例來(lái)詳細(xì)的說(shuō)明一下。

dll文件不匹配導(dǎo)致數(shù)據(jù)庫(kù)無(wú)法啟動(dòng)

前段時(shí)間,數(shù)據(jù)庫(kù)做了一些功能上的改進(jìn),于是用VS2010編譯檢出了一個(gè)版本,供測(cè)試部測(cè)試。測(cè)試部拿到數(shù)據(jù)庫(kù)后,通過(guò)批處理將數(shù)據(jù)庫(kù)程序,注冊(cè)為服務(wù)。雖然執(zhí)行的是批處理,實(shí)際上注冊(cè)服務(wù)的過(guò)程,是通過(guò)運(yùn)行數(shù)據(jù)庫(kù)程序,并給其傳入命令行參數(shù)來(lái)完成的,詳情請(qǐng)看這篇文章玩轉(zhuǎn)Windows服務(wù)系列——Debug、Release版本的注冊(cè)和卸載,及其原理。

通過(guò)批處理運(yùn)行程序后,出現(xiàn)如下問(wèn)題:

應(yīng)用程序無(wú)法啟動(dòng)

出現(xiàn)這種問(wèn)題,測(cè)試部不淡定了,叫我去看。我又試著運(yùn)行了一下程序,依然出現(xiàn)這個(gè)問(wèn)題。“可是在我的機(jī)器上運(yùn)行的挺好的啊”,這是我說(shuō)的第一句話,相信很多人看了這句話就會(huì)心的笑了。

有問(wèn)題就是有問(wèn)題,既然我的機(jī)器上可以正常運(yùn)行,那么測(cè)試機(jī)為什么不行呢,首先要查找原因。

數(shù)據(jù)庫(kù)是用VS2010編譯的,那么在其他機(jī)器上運(yùn)行,就需要運(yùn)行的操作系統(tǒng)中以及安裝了VS2010的運(yùn)行時(shí),否則就會(huì)因?yàn)槿鄙俪绦蜻\(yùn)行所必須的dll文件而無(wú)法正常運(yùn)行。我想應(yīng)該是這個(gè)原因,但又一想,如果沒(méi)有裝運(yùn)行時(shí)的話,會(huì)提示缺少msvcr100.dll、msvcp100.dll等文件,上圖中的問(wèn)題顯然不是缺少dll問(wèn)題。問(wèn)題有點(diǎn)復(fù)雜,為了簡(jiǎn)單,先試著安裝運(yùn)行時(shí),看能不能解決吧。

將VS2010的x86和x64 Runtime安裝包全裝了一遍。再運(yùn)行程序,依然是這個(gè)醒目的錯(cuò)誤。

雖然安裝運(yùn)行時(shí)沒(méi)有解決這個(gè)問(wèn)題,但根據(jù)經(jīng)驗(yàn)判斷,要么是缺少dll文件,要么就是dll文件版本出了問(wèn)題。那么,接下來(lái)就是想辦法證明這個(gè)猜想。

通過(guò)Dependency Walker檢測(cè)數(shù)據(jù)庫(kù)程序,所有依賴的dll文件都存在,沒(méi)有發(fā)現(xiàn)什么問(wèn)題。然后通過(guò)Windows Sysinternals中的ListDLLs工具檢測(cè)當(dāng)前運(yùn)行的進(jìn)程已經(jīng)加載的dll文件,從列表中看到msvcr100.dll沒(méi)有加載,估計(jì)就是這個(gè)dll文件出了問(wèn)題。從我的機(jī)器上找到這個(gè)文件,替換了測(cè)試機(jī)上的msvcr100.dll文件后,數(shù)據(jù)庫(kù)就正常運(yùn)行了。

原來(lái),剛剛啟動(dòng)數(shù)據(jù)庫(kù)的時(shí)候,提示找不到msvcr100.dll文件,測(cè)試的同事就從其他的XP系統(tǒng)的機(jī)器上找了這個(gè)文件,并分別放入到System32和SysWow64中,于是就導(dǎo)致了上圖中的這個(gè)問(wèn)題。

由于XP系統(tǒng)是32位的,所以找到的msvcr100.dll文件也是32位,當(dāng)把這個(gè)32位程序放到System32文件夾后,啟動(dòng)64位數(shù)據(jù)庫(kù),就會(huì)加載這個(gè)32位dll,由于64位程序只能加載64位dll,所以當(dāng)程序嘗試加載32位dll時(shí),就會(huì)報(bào)錯(cuò)了。

究竟是System32還是SysWow64

Win7、Server2008等64位系統(tǒng)出來(lái)以后,為了兼容32位程序,所以采用了Wow64方案,在系統(tǒng)文件夾中,可以看到一個(gè)System32文件夾,和一個(gè)SysWow64文件夾。雖然這個(gè)方案對(duì)于程序來(lái)說(shuō),可以很方便的兼容32位程序,但是對(duì)于一般用戶來(lái)說(shuō),想分辨System32和SysWow64那就有點(diǎn)困難了,因?yàn)槊痔忻曰笮粤恕?/p>

至于微軟為什么采用Wow64方案,我就不細(xì)說(shuō)了,感興趣的朋友可以看這篇文章:什么是SysWow64。這篇文章詳細(xì)的介紹了Wow64技術(shù),以及64位系統(tǒng)兼容32位程序的情況。

最后,我們可以知道:

  • SysWow64文件夾,是64位Windows,用來(lái)存放32位Windows系統(tǒng)文件的地方,而System32文件夾,是用來(lái)存放64位程序文件的地方。
  • 當(dāng)32位程序加載System32文件夾中的dll時(shí),操作系統(tǒng)會(huì)自動(dòng)映射到SysWow64文件夾中的對(duì)應(yīng)的文件。

看到這些,你一定會(huì)認(rèn)為你真正的明白了System32和SysWow64的區(qū)別,我也一樣,我以為我真的懂了,但是真的懂了嗎,是真懂了嗎?

無(wú)論怎樣還是請(qǐng)你堅(jiān)持看完。

區(qū)分dll文件32位64位的程序讓我倍感迷惑

上面說(shuō)到的數(shù)據(jù)庫(kù)無(wú)法啟動(dòng)的這種情況,已經(jīng)遇到了不止一次了。每次遇到這種問(wèn)題,我都想能不能有個(gè)工具可以檢查System32和SysWow64文件夾中的dll程序是不是對(duì)應(yīng)的64位和32位程序。據(jù)我所知只有dumpbin可以查看一個(gè)dll文件是32位還是64位,但它明顯不是我想要的工具,因?yàn)槊看沃荒懿榭匆粋€(gè)文件。

好吧,自己動(dòng)手,豐衣足食,既然沒(méi)有這種工具,那就來(lái)寫一個(gè)吧,好在判斷dll文件是32位還是64位也不是很難。

Windows系統(tǒng)下,exe、dll文件都可以稱為PE文件,他們有相同的文件格式,稱為PE文件格式。

PE文件的第一個(gè)部分是IMAGE_DOS_HEADER,大小為64B,對(duì)于檢查32位64位來(lái)說(shuō),有一個(gè)重要的成員e_lfanew,這個(gè)成員的值為IMAGE_NT_HEADERS的偏移。

IMAGE_DOS_HEADER的定義如下:

typedef struct _IMAGE_DOS_HEADER{//(注:最左邊是文件頭的偏移量。)+0h  Word e_magic         //Magic DOS signature MZ(4Dh 5Ah)         DOS可執(zhí)行文件標(biāo)記+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代碼的初始化指令入口[指針I(yè)P]+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 字段:在一個(gè)有效的 PE 文件里,Signature 字段被設(shè)置為00004550h,ASCII 碼字符是“PE00”。標(biāo)志這 PE 文件頭的開(kāi)始。“PE00” 字符串是 PE 文件頭的開(kāi)始,DOS 頭部的 e_lfanew 字段正是指向這里。

IMAGE_FILE_HEADER 結(jié)構(gòu)定義:

typedef struct _IMAGE_FILE_HEADER {+04h  WORD  Machine;                        // 運(yùn)行平臺(tái)+06h  WORD  NumberOfSections;               // 文件的區(qū)塊數(shù)目+08h  DWORD TimeDateStamp;                  // 文件創(chuàng)建日期和時(shí)間+0Ch  DWORD PointerToSymbolTable;           // 指向符號(hào)表(主要用于調(diào)試)+10h  DWORD NumberOfSymbols;                // 符號(hào)表中符號(hào)個(gè)數(shù)(同上)+14h  WORD  SizeOfOptionalHeader;           // IMAGE_OPTIONAL_HEADER32 結(jié)構(gòu)大小+16h  WORD  Characteristics;                // 文件屬性} IMAGE_FILE_HEADER;

其中Machine字段表示可執(zhí)行文件的目標(biāo)CPU類型:

  • IMAGE_FILE_MACHINE_I386         0x014c   x86
  • IMAGE_FILE_MACHINE_IA64         0x0200   Intel Itanium
  • IMAGE_FILE_MACHINE_AMD64        0x8664  x64

這樣不是很直觀,上張圖來(lái)看一下:

32位64位PE文件

有了這些,我們就可以通過(guò)程序來(lái)判斷32位、64位了,代碼如下:

public static bool IsPE32(string path){    FileStream file = File.OpenRead(path);    //移動(dòng)到e_lfanew的位置處    stream.Seek(0x40 - 4, SeekOrigin.Begin);    byte[] buf = new byte[4];    stream.Read(buf, 0, buf.Length);    //根據(jù)e_lfanew的值計(jì)算出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;    }}

最核心的功能完成了,剩下的就是界面和遍歷文件夾了,效果圖:

檢測(cè)效果圖

根據(jù)檢測(cè)結(jié)果和實(shí)際情況判斷,檢測(cè)結(jié)果沒(méi)問(wèn)題。那么就開(kāi)始真正的檢測(cè)吧,System32和SysWow64。檢測(cè)結(jié)果如下圖:

32位程序System32SysWow64檢測(cè)結(jié)果對(duì)比

從圖中看出,System32、SysWow64中檢測(cè)出的所有的文件均為32位程序,根據(jù)常識(shí)也可以判斷出,實(shí)際肯定不是這樣的。一定是程序出了什么問(wèn)題,那么直接用十六進(jìn)制編輯器看一下兩個(gè)文件是否一致吧。

再次判斷究竟是System32還是SysWow64——意想不到的坑

通過(guò)UE查看兩個(gè)文件夾中的msvcr110d.dll確實(shí)都是32位程序,而且用Beyond Compare進(jìn)行比較,兩個(gè)文件也沒(méi)有差異。用工具查看兩個(gè)文件的md5也是完全一致:

System32_SysWow64_msvcr110d_md5

難道兩個(gè)文件真的都是32位嗎,我還是覺(jué)得不太可能。

接下來(lái)將System32和SysWow64中的msvcr110d.dll分別移動(dòng)到其他文件夾,這樣System32和SysWow64就沒(méi)有這個(gè)dll文件了,然后運(yùn)行一個(gè)32位的需要這個(gè)dll文件的程序PeTest,提示找不到這個(gè)dll文件。分別將原來(lái)System32和SysWow64中的msvcr110.dll拷貝到這個(gè)PeTest所在的目錄,運(yùn)行程序。當(dāng)使用SysWow64中的msvcr110d.dll時(shí),程序可以正常運(yùn)行,說(shuō)明這個(gè)文件確實(shí)是32位。當(dāng)使用System32中的msvcr110d.dll時(shí),程序無(wú)法正常運(yùn)行,出現(xiàn)文章開(kāi)始時(shí)提到的錯(cuò)誤。為什么通過(guò)Beyond C

上一篇:CLR via C#

下一篇:裝箱算法實(shí)驗(yàn)

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 昌吉市| 山阳县| 彰化县| 和顺县| 宁波市| 墨脱县| 绿春县| 泰和县| 中阳县| 钟山县| 巴林右旗| 施秉县| 甘洛县| 颍上县| 三明市| 汉寿县| 贡觉县| 嘉义市| 高阳县| 习水县| 青铜峡市| 左权县| 长岭县| 大石桥市| 德安县| 木兰县| 永和县| 武清区| 清河县| 泽普县| 英山县| 怀远县| 久治县| 临澧县| 六盘水市| 双江| 洮南市| 仁布县| 合川市| 无棣县| 张家港市|