VC编写的程序不能在其他机器上运行的解决方案(续)
我在前面的文章里面提到由于side-by-side問題導致的VC編寫的程序不能正常啟動的問題的解決方案,這種方法是針對于單個可執行文件的解決方案,但是有的時候你可能會碰到另外一種情況—也是由于side-by-side問題導致的,你的程序支持插件,當你的程序試圖加載一個依賴于CRT的DLL的時候,Windows告訴你不能加載DLL。
?
比如微軟在06年發布了CLR的開源版本,你在自己機器上用Visual Studio 2008編譯以后,在使用Windbg + SOS調試托管代碼的時候,Windbg可能會報告無法加載SOS的錯誤,例如下面的Windbg輸出:
| CommandLine: binaries.x86dbg.rotor"clix.exe pptclrt"ForAndForeach.exe Executable search path is: ModLoad: 7c800000 7c91e000?? C:"WINDOWS"system32"kernel32.dll … ModLoad: 79e00000 79e0a000?? C:"sscli20"binaries.x86dbg.rotor"sscoree.dll (1484.1358): Break instruction exception - code 80000003 (first chance) … ntdll!DbgBreakPoint: 7c92120e cc?????????? ???int???? 3 0:000> .load C:"sscli20"binaries.x86dbg.rotor"sos.dll The call to LoadLibrary(C:"sscli20"binaries.x86dbg.rotor"sos.dll) failed, Win32 error 0n126 ??? "找不到指定的模塊。" Please check your debugger configuration and/or network access. |
1.?????????當你在C:"sscli20"binaries.x86dbg.rotor"查看sos.dll是否存在的時候,將會驚訝地發現sos.dll靜靜地躺在文件夾里面等待別人發現它!然而為什么Windbg在調用操作系統LoadLibrary API的時候,操作系統會報告說“找不到指定的模塊”呢?
2.?????????再仔細看一下,文件夾里面有sos.dll.manifest文件,確認一下內容,里面依賴的CRT版本的的確確是我們機器上安裝好了的CRT版本呀!
| <?xml?version='1.0'?encoding='UTF-8'?standalone='yes'?> <assembly?xmlns='urn:schemas-microsoft-com:asm.v1'?manifestVersion='1.0'> ?<trustInfo?xmlns="urn:schemas-microsoft-com:asm.v3"> ??? <security> ????? <requestedPrivileges> ??????? <requestedExecutionLevel?level='asInvoker'?uiAccess='false'?/> ????? </requestedPrivileges> ??? </security> ?</trustInfo> ?<dependency> ??? <dependentAssembly> ????? <assemblyIdentity?type='win32'?name='Microsoft.VC90.DebugCRT'version='9.0.21022.8'?processorArchitecture='x86'publicKeyToken='1fc8b3b9a1e18e3b'?/> ??? </dependentAssembly> ?</dependency> </assembly> |
?
3.?????????于是我們猜測,可能是操作系統在加載dll的時候,并不查看dll的manifest文件,也就不會去加載CRT,從而導致SOS.DLL加載失敗。
4.?????????那既然是懷疑操作系統不會根據dll的manifest文件來加載CRT的話,那我們是不是可以為Windbg.exe創建一個manifest文件來告訴操作系統在運行windbg的時候先把CRT加載進內存,然后在SOS加載的時候,因為CRT已經提前加載進Windbg的進程中了,也就不會有依賴項不能加載而導致SOS加載失敗的問題了。
5.?????????接著將sos.dll.manifest復制一份并且重命名為windbg.exe.manifest,最后把它放到windbg.exe同一個文件夾里面去。再啟動windbg加載sos試一下,還是不行,郁悶!
?
難道就像以前昭君出塞的故事一樣,是因為SOS.DLL沒有潛規則導致操作系統不愿意加載它?
| 據《西京雜記》的描述,元帝后宮的美女實在太多了,根本不可能一個個當面鑒賞。他便讓“黃門畫者”(宮廷畫工)把她們的肖像全都畫出來,交給自己挑選。 ? 宮女們的命運鬼使神差地掌握在了畫工們的手中,她們便爭相向這些畫工行賄,多則10萬錢,再少也不低于5萬錢。負責給王昭君畫像的畫工叫毛延壽,王昭君自恃才貌雙絕,不愿屈身相求,更拿不出這么多錢來賄賂他。毛延壽便在她的臉上隨手點了一顆黑痣。 ? 元帝對這么一個并不完美的女子,自然提不起興趣。因此,王昭君入宮好幾年,都沒有機會被召幸,內心的委屈與悲怨不言而喻。 |
?
正如哥們我仍然單身,一定不能放過一個美女一樣!我們也不能讓這種問題就此埋沒下去,于是我們再次想起mt.exe程序,實際上我們應該叫它(mp.exe –?媒婆.exe),:)
讓我們看看Windbg資源里面是否已經嵌入一個manifest文件了,才導致我們自己加的manifest沒有作用,使用下面的命令看一看:
mt -inputresource:d:"Debuggers"windbg.exe;#1 -output:test.manifest
哼哼,果然有一個:
| <?xml?version="1.0"?encoding="UTF-8"?standalone="yes"?> <assembly?xmlns="urn:schemas-microsoft-com:asm.v1"?manifestVersion="1.0"> <assemblyIdentity?name="Microsoft.Windows.SdkTools.windbg"?processorArchitecture="x86"version="6.9.0.0"?type="win32"></assemblyIdentity> <description>Windows GUI symbolic debugger</description> <dependency> ??? <dependentAssembly> ??????? <assemblyIdentity?type="win32"?name="Microsoft.Windows.Common-Controls"version="6.0.0.0"?processorArchitecture="*"?publicKeyToken="6595b64144ccf1df"?language="*"></assemblyIdentity> ??? </dependentAssembly> </dependency> </assembly> |
但是里面并沒有說windbg不依賴CRT,因此操作系統就隨便加載了一個CRT敷衍了事了,既然知道問題所在了,那么我們要做的事情就比較簡單了,將Windbg資源里面的manifest文件更新一下,然后再將Debug CRT包拷貝到Windbg同一個目錄里面就可以了。
?
1.?????????將test.manifest文件更新成:
| <?xml?version="1.0"?encoding="UTF-8"?standalone="yes"?> <assembly?xmlns="urn:schemas-microsoft-com:asm.v1"?manifestVersion="1.0"> <assemblyIdentity?name="Microsoft.Windows.SdkTools.windbg"processorArchitecture="x86"?version="6.9.0.0"?type="win32"></assemblyIdentity> <description>Windows GUI symbolic debugger</description> <dependency> ??? <dependentAssembly> ??????? <assemblyIdentity?type="win32"?name="Microsoft.Windows.Common-Controls"version="6.0.0.0"?processorArchitecture="*"?publicKeyToken="6595b64144ccf1df"language="*"></assemblyIdentity> ??? </dependentAssembly> </dependency> ? ?<dependency> ??? <dependentAssembly> ????? <assemblyIdentity?type='win32'?name='Microsoft.VC90.DebugCRT'version='9.0.21022.8'?processorArchitecture='x86'publicKeyToken='1fc8b3b9a1e18e3b'?/> ??? </dependentAssembly> ?</dependency> </assembly> |
?
2.?????????執行命令將Windbg資源里面的manifest文件更新一下。
mt -updateresource:d:"Debuggers"windbg.exe;#1 -manifest test.manifest
總結
以上是生活随笔為你收集整理的VC编写的程序不能在其他机器上运行的解决方案(续)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php pdf 文字水印图片,php如何
- 下一篇: VS 中配置使用Visual SVN系列