Manifest是個XML的描述文件,對於每個DLL有DLL的Manifest文件,對於每個應用程序Application也有自己的Manifest。對於應用程序而言,Manifest可以是一個和exe文件同一目錄下的.manifest文件,也可以是作爲一個資源嵌入在exe文件內部的(Embed Manifest)。
XP以前版本的windows,會像以前那樣執行這個exe文件,尋找相應的dll,沒有分別Manifest只是個多餘的文件或資源,dll文件會直接到system32的目錄下查找,並且調用。這樣,如果公共DLL升級,將會導致之前安裝的應用程序不能使用,這就是“DLL Hell”的來源。爲了解決這個問題,.NET開發提出了side-by-by的開發方法,來避免這個問題。主要方法,就是通過Manifest文件來查找相應的DLL。XP及以後的系統都集成了這樣一種查找DLL的方法。
提取Manifest
默認Manifest文件都是內嵌在exe/dll中的,如果需要查看。VS提供mt.exe工具來從exe/dll中提取Manifest文件。
mt.exe -inputresource:d:\test.exe -out:d:\test.manifest
的Manifest文件有關設置
我們編譯MFC工程時,會在stdafx.h文件裏看到下列代碼。
#ifdef _UNICODE #if defined _M_IX86 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_IA64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_X64 #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") #else #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #endif #endif
如果是非unicode版本,則生成的界面是Win98風格,如果是unicdoe版本,則是當前操作系統的風格。 Linker→Manifest file→Generate Manifest→yes 即會生成EXE/DLL所用的Manifest文件。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.MFC' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*' /> </dependentAssembly> </dependency> </assembly>
如果沒有設置上面的控件風格,則生成的Manifest不會包括contrls.
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC80.MFC' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> </assembly>
所有的exe/dllFT都必須要有Manifest。如果Linker→Manifest file→Generate Manifest→No,則在必須Manifest Tool→Additinal Manifest Files中指定相應的Manifest文件。 Manifest Tool→Embed Manifest→Yes。一般都是將Manifest文件嵌套在程序中。也可以不嵌套在程序中,像MFCxx.dll, MSVCRxx.Dll,MSVCPxx.dll都是沒有將Manifest嵌套在程序中的。所以當使用它們時必須與其Manifest文件一起使用。
EXE調用DLL的過程
以下針對鏈接MFCxx.dll, MSVCPXX.DLL, MSVCRxx.dll的程序。
系統啓動exe時,會先檢查其Manifest文件(如果沒有查找到當前EXE中有Manifest,則會報“程序配置不正確的”的錯誤提示),查找系統中是否有註冊相應的Dll組件。如果有,則會去c:\windows\winsxs\Manifest文件夾根據相應的調用策略及Manifest文件,然後再根據Manifest中的內容去c:\windows\winsxs同名文件夾中查找到關的DLL。
如果沒有查找到相應的DLL,則會到當前目錄來查找Microsoft.VC80.CRT.manifest和Microsoft.VC80.MFC.manifest。
如果沒有查找到當前EXE中有Manifest,則會報“程序配置不正確的”的錯誤提示。查到之後,就會去找相應的DLL。然後執行程序。
相關DLL介紹
選擇Use MFC in share DLL會用到MFCxx.DLL. MFC80.dll, 即對應VS2005的。 MFC80U.DLL,即對應VS2005的Unicode版本。
選擇MD/MDd則會用到下面的DLL。 MSVCR80.dll,即VS2005下的C RunTime庫,提供基本的C函數。 MSVCP80.dll, 即VS2005年的C++函數庫,如果有調用<string>之類的文件,則會使用到此DLL。
注意
1、X86、X64需要去VS工具目錄
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\x86 C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\redist\x64
2、Manifest文件自VS2010之後,又被集成到模塊當中去了,不再分開提供。