久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

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

 bubbi7 2016-12-17

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

dll文件不匹配導致數(shù)據(jù)庫無法啟動

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

通過批處理運行程序后,出現(xiàn)如下問題:

應用程序無法啟動

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

有問題就是有問題,,既然我的機器上可以正常運行,,那么測試機為什么不行呢,首先要查找原因,。

數(shù)據(jù)庫是用VS2010編譯的,,那么在其他機器上運行,就需要運行的操作系統(tǒng)中以及安裝了VS2010的運行時,,否則就會因為缺少程序運行所必須的dll文件而無法正常運行,。我想應該是這個原因,但又一想,,如果沒有裝運行時的話,,會提示缺少msvcr100.dll、msvcp100.dll等文件,,上圖中的問題顯然不是缺少dll問題,。問題有點復雜,為了簡單,先試著安裝運行時,,看能不能解決吧,。

將VS2010的x86和x64 Runtime安裝包全裝了一遍。再運行程序,,依然是這個醒目的錯誤,。

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

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

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

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

究竟是System32還是SysWow64

Win7、Server2008等64位系統(tǒng)出來以后,,為了兼容32位程序,,所以采用了Wow64方案,在系統(tǒng)文件夾中,,可以看到一個System32文件夾,,和一個SysWow64文件夾,。雖然這個方案對于程序來說,可以很方便的兼容32位程序,,但是對于一般用戶來說,,想分辨System32和SysWow64那就有點困難了,因為名字太有迷惑性了,。

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

最后,,我們可以知道:

  • SysWow64文件夾,,是64位Windows,用來存放32位Windows系統(tǒng)文件的地方,,而System32文件夾,,是用來存放64位程序文件的地方。
  • 當32位程序加載System32文件夾中的dll時,,操作系統(tǒng)會自動映射到SysWow64文件夾中的對應的文件,。

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

無論怎樣還是請你堅持看完。

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

上面說到的數(shù)據(jù)庫無法啟動的這種情況,,已經(jīng)遇到了不止一次了,。每次遇到這種問題,我都想能不能有個工具可以檢查System32和SysWow64文件夾中的dll程序是不是對應的64位和32位程序,。據(jù)我所知只有dumpbin可以查看一個dll文件是32位還是64位,,但它明顯不是我想要的工具,因為每次只能查看一個文件,。

好吧,,自己動手,豐衣足食,,既然沒有這種工具,,那就來寫一個吧,好在判斷dll文件是32位還是64位也不是很難。

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

PE文件的第一個部分是IMAGE_DOS_HEADER,大小為64B,,對于檢查32位64位來說,,有一個重要的成員e_lfanew,這個成員的值為IMAGE_NT_HEADERS的偏移,。

IMAGE_DOS_HEADER的定義如下:

Collapse
復制代碼
typedef struct _IMAGE_DOS_HEADER
{//(注:最左邊是文件頭的偏移量,。)
+0h  WORD e_magic         //Magic DOS signature MZ(4Dh 5Ah)         DOS可執(zhí)行文件標記
+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的定義如下:

Collapse
復制代碼
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 文件頭的開始?!癙E00” 字符串是 PE 文件頭的開始,,DOS 頭部的 e_lfanew 字段正是指向這里。

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

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

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

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

這樣不是很直觀,,上張圖來看一下:

32位64位PE文件

有了這些,,我們就可以通過程序來判斷32位、64位了,,代碼如下:

Collapse
復制代碼
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);
    //根據(jù)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;
    }
}
復制代碼

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

檢測效果圖

根據(jù)檢測結(jié)果和實際情況判斷,檢測結(jié)果沒問題,。那么就開始真正的檢測吧,,System32和SysWow64。檢測結(jié)果如下圖:

32位程序System32SysWow64檢測結(jié)果對比

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

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

通過UE查看兩個文件夾中的msvcr110d.dll確實都是32位程序,而且用Beyond Compare進行比較,兩個文件也沒有差異,。用工具查看兩個文件的MD5也是完全一致:

System32_SysWow64_msvcr110d_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時,,程序無法正常運行,,出現(xiàn)文章開始時提到的錯誤。為什么通過Beyond Compare,、UE,、MD5檢測為同樣的dll文件,一個可以正常運行,,另外一個就不可以呢,。

再次思考這兩句話:

  • SysWow64文件夾,是64位Windows,,用來存放32位Windows系統(tǒng)文件的地方,,而System32文件夾,是用來存放64位程序文件的地方,。
  • 當32位程序加載System32文件夾中的dll時,,操作系統(tǒng)會自動映射到SysWow64文件夾中的對應的文件。

32位程序加載System32文件夾中的dll文件,,操作系統(tǒng)會自動映射到SysWow64文件夾,,也就是說64位程序,系統(tǒng)不會再做映射,。

通過任務管理器查看UE,、Beyond Compare和MD5三個進程全部為32位進程,即三個程序全部是32位,。

至此我們可以重新理解“32位程序加載System32文件夾中的dll文件,,操作系統(tǒng)會自動映射到SysWow64文件夾”這句話,應該是“只要32位程序訪問System32文件夾,,無論是加載dll,,還是讀取文本信息,,都會被映射到SysWow64文件夾”。

這個理解對嗎,,我們來做一個實驗驗證一下,。

找一個32位的文本編輯器Notepad++(Win7系統(tǒng)自帶的是64位),在SysWow64文件夾中新建一個1.txt的文件,,打開編輯此文件,,內(nèi)容為SysWow64。然后在打開文件對話框中的輸入框中輸入“C:\Windows\System32\1.txt”,,打開文件,,看到內(nèi)容為SysWow64,如圖所示:

System32_SysWow64_文本文件

System32中沒有創(chuàng)建1.txt文件,,32位程序訪問System32中的1.txt文件,,被自動映射到SysWow64文件夾中的1.txt文件,而如果用64位的Notepad編輯器打開System32中的1.txt文件,,就會提示找不到文件:

Notepad_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的方式來驗證,,發(fā)現(xiàn)當32位程序訪問Program Files目錄時,,并沒有被映射到Program Files (x86)目錄。

32位程序真的需要訪問System32嗎

經(jīng)過了這么多驗證,,總算是知道32位程序無法訪問System32,,只有64位程序才能訪問,由此認為,,這是Windows的一個非常大的坑,。但是仔細想想,32位程序真的需要訪問System32嗎,。就用這個dll檢測工具來說吧,。

如果在64位系統(tǒng)上,32位程序無法訪問System32,,為了訪問它,,就需要編譯為64位。而如果程序編譯為64位,,就無法在32位系統(tǒng)上運行,,同時由于在32位系統(tǒng)上不需要檢測32位、64位,,所以只需要32位程序即可,。這可真是一個矛盾的事情,難道必須編譯兩個程序,,一個32位,,一個64位,來適應不同的操作系統(tǒng)嗎,。如果是C++的話,,那么答案是這樣的,必須編譯一個32位一個64位,。而DotNet就不一樣了,,編譯的時候選擇“AnyCPU”,并且不選擇“首選32位”(VS2012中默認選中),,編譯后的程序,,可以同時在32位和64位系統(tǒng)上運行,32位系統(tǒng)上是32位進程,,64位系統(tǒng)上是64位進程,,是不是很方便呢,這正是DotNet和AnyCPU的魅力所在,。

至此,,dll檢測程序,不需要做任何代碼修改,,只需在編譯的時候選擇AnyCPU,,并去掉“首選32位”選項,即可正常檢測System32,、SysWow64文件夾中的dll文件,。

32位程序與64位程序的區(qū)別總結(jié)

至此,我想應該是真的明白了System32與SysWow64的區(qū)別了吧,,這個不大不小的坑,,算是邁過去了,那么就來總結(jié)一下32位程序與64位程序的區(qū)別:

  • SysWow64文件夾,,是64位Windows,,用來存放32位Windows系統(tǒng)文件的地方,而System32文件夾,,是用來存放64位程序文件的地方,。
  • .Net程序以AnyCPU配置,并選擇“首選32位”編譯,,會以32位的進程運行,,此時就無法訪問System32文件夾中的文件,;如果沒有選擇“首選32位”,則會以64位的進程運行,,這樣就可以訪問System32文件夾了,。(VS2012中,“首選32位”默認是選中的),。
  • 32位程序的尋址空間有限,,最多達到4G,而64位程序的尋址空間可以達到TB級,,想要使用大內(nèi)存的話,,就升級到64位吧,好在DotNet程序從32位升級到64位比較簡單,,不像C++那么麻煩,。
  • 32位程序訪問System32目錄,會自動被映射到SysWOW64目錄,,而64位程序可以訪問System32目錄和SysWOW64目錄,。
  • 32位程序與64位程序有各自的注冊表。
  • 32位與64位程序都可以訪問Program Files (x86)與Program Files目錄,。
  • 更多區(qū)別可以參考:32-bit and 64-bit Windows: frequently asked questions,。

工作與學習過程中會遇到很多坑,一不小心就會跌倒,,但是從哪里跌倒的就從哪里爬起來,,總結(jié)經(jīng)驗教訓,以飽滿的熱情再次起航,,勝利就在不遠的前方,。

由于本人水平有限,文中如有不對之處,,還請批評指正,,本人不勝感激!

參考資料

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多