VC编写的程序不能在其他机器上运行的解决方案
有的時(shí)候,你在Visual C++上面經(jīng)過好幾個(gè)月的辛勤努力,終于將程序編寫完成并且測試完畢,然而當(dāng)你試圖在客戶的發(fā)布機(jī)上運(yùn)行剛寫好的程序時(shí),有可能會(huì)碰到類似下面的錯(cuò)誤,操作系統(tǒng)告訴你“由于應(yīng)用程序配置不正確,應(yīng)用程序未能啟動(dòng)。重新安裝應(yīng)用程序可能會(huì)糾正這個(gè)問題”:
?
?
一般情況下,這個(gè)問題都是由于程序不能找到所需要的C運(yùn)行庫(CRT)而引起的。
?
在Windows XP SP2以后,Windows引入了Side-by-Side執(zhí)行的概念,這個(gè)概念本來是.NET提出來的,但是Windows后來將這個(gè)概念集成到操作系統(tǒng)層面上來了。大家都應(yīng)該知道Dll Hell的問題,為了解決Dll Hell的問題,Side-By-Side提出不同版本的dll文件可以同時(shí)存在于同一個(gè)系統(tǒng)里面,而且依賴于不同版本dll的應(yīng)用程序在運(yùn)行的時(shí)候可以使用到它當(dāng)初被編譯生成的dll。前面的話,有點(diǎn)繞,舉個(gè)例子:
1.?????????假定你編寫了一個(gè)C++程序A,是使用MFC 8.0(這個(gè)版本是隨著Visual Studio 2005)發(fā)布的。
2.?????????之后你的機(jī)器升級(jí)了Visual Studio的版本,從2005升級(jí)到2008,2008的MFC庫是9.0版本的,這個(gè)時(shí)候你的操作系統(tǒng)里面安裝了兩個(gè)版本的MFC,分別是8.0和9.0。
3.?????????你在Visual Studio 2008編寫了另外一個(gè)C++程序B,B依賴與MFC 9.0。
4.?????????如果你運(yùn)行程序A的話,操作系統(tǒng)會(huì)將MFC 8.0加載到A的進(jìn)程里面。
5.?????????如果你這時(shí)同時(shí)運(yùn)行程序B,操作系統(tǒng)會(huì)將MFC 9.0加載到B的進(jìn)程里面。這就是Side-by-side的執(zhí)行概念。
?
操作系統(tǒng)之所以能夠這樣做,是因?yàn)樗诩虞d程序A和B之前,除了查看PE格式里面A和B所依賴的Dll信息,都會(huì)查看A和B的manifest文件。Manifest文件保存了Windows可執(zhí)行文件(包括exe和dll文件)要運(yùn)行起來的環(huán)境設(shè)置信息,文件名一般是可執(zhí)行文件的文件全名加上.manifest。例如notepad.exe的manifest文件就應(yīng)該是notepad.exe.manifest。例外有的程序?qū)anifest文件直接嵌入到可執(zhí)行文件的資源里面了,這也就是為什么有的時(shí)候你看不到程序的manifest文件的原因。通常來說,一個(gè)manifest文件的內(nèi)容如下(test.exe.manifest文件):
| <?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> |
上面的例子里面,就說明這個(gè)程序依賴于CRT 9.0,而且是調(diào)試版的,CPU架構(gòu)是32位的CPU。對(duì)于將manifest文件嵌入到資源文件的程序我們也有辦法看到manifest的信息。
1.?????????一種是使用mt.exe(Visual Studio自帶的manifest處理程序):
mt -inputresource:test.exe;#1 /out:test.manifest
2.?????????另外一種是使用dumpbin程序?qū)⒄麄€(gè)exe的內(nèi)容打印到一個(gè)文件,然后用文本編輯器打開,搜索Assem字符串樣式就能找到manifest信息:
?
解決方案
知道了程序依賴于具體哪一個(gè)dll以后,你可以將所依賴的dll拷貝到程序的安裝文件夾里面,以CRT庫綁定失敗為例,介紹解決步驟:
1.?????????從上例中我們知道程序依賴的Microsoft.VC90.DebugCRT庫,版本號(hào)是9.0.21022.8,需要32位機(jī)器版本的CRT。這個(gè)依賴項(xiàng)一般是因?yàn)槟愕某绦蚴钦{(diào)試版,所以Visual Studio在編譯的時(shí)候,將調(diào)試版的CRT加入程序的依賴項(xiàng)。
2.?????????從Visual Studio的安裝文件夾里面將D:"Program Files"Microsoft Visual Studio 9.0"VC"redist"Debug_NonRedist"x86中的Microsoft.VC90.DebugCRT整個(gè)文件夾拷貝到應(yīng)用程序所在的文件夾里面,注意:
a)?????????如果你的程序依賴的是32位的CRT,則要拷貝x86文件夾里面的Microsoft.VC90.DebugCRT文件夾,如果是先x64程序,則要拷貝x64文件夾里面。
b)?????????你需要確定Microsoft.VC90.DebugCRT文件夾里面的Microsoft.VC90.DebugCRT.manifest文件里面保存的版本信息而你程序依賴的版本信息匹配,Microsoft.VC90.DebugCRT.manifest里面的版本信息大版本號(hào)一定要一致,小版本號(hào)一定要等于或者大于你程序依賴的CRT的小版本號(hào)。比如上例中,我們的程序是依賴于CRT 9.0.21022.8,而我們的Microsoft.VC90.DebugCRT.manifest的版本是9.0.30729.1,這樣是可以的;而8.0.30729.1就會(huì)有問題。如果大版本號(hào)一樣,小版本號(hào)不一致的話,一個(gè)比較簡單的方案就是修改程序的manifest文件,使其互相匹配就可以了。
3.?????????如果你的程序不是依賴調(diào)試版本的CRT,而是release版本的CRT,直接去微軟的官方網(wǎng)站下載一個(gè)crt redist包安裝上就可以了。
總結(jié)
以上是生活随笔為你收集整理的VC编写的程序不能在其他机器上运行的解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构 排序 java_Java数据结
- 下一篇: VC编写的程序不能在其他机器上运行的解决