VS2008環境下開發的某些程序在其他機器運行提示“由於應用程序配置不正確,應用程序未能啟動”的問題(IIS)


比較全的有關vs2008部署問題集(1):

http://blog.csdn.net/buhuizheyangba/article/details/7220598

比較全的有關vs2008部署問題集(2):

http://blog.csdn.net/fengbingchun/article/details/6449241

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

原文地址:http://www.360doc.com/content/11/0125/17/61151_88963969.shtml

VC9編譯的程序在沒有裝過VC9(確切的說是.Net Framework3.5)的機器上運行時,如果提示“由於應用程序配置不正確,應用程序未能啟動。重新安裝應用程序可能會糾正這個問題。”這個錯誤,那么就說明該程序動態鏈接了VC9的運行時庫,(如果還用到了MFC,那么可能動態鏈接了VC9的MFC庫,同理還有ATL庫),以及缺少對應的 manifest文件,程序在目標機器上沒有找到這些庫和配置文件,因此導致了這個錯誤。出現這種情況的VC9編譯器可能存在3個版本,接下來分別闡明:

1、沒有打過任何補丁的VS2008

該版本對應的CRT/MFC/ATL庫的版本號為9.0.21022.8,這個版本號在后面會用到。這個版本的程序部署比較簡單,直接把VC安裝目錄下的redist目錄(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的庫以及對應的manifest文件拷貝到執行程序同目錄下,這樣程序到任何機器上都能夠正常運行了。

2、打過SP1補丁的VS2008

打過該補丁后,系統中存在着兩個版本的CRT/MFC/ATL庫,版本號分別為9.0.21022.8和9.0.30729.1,這導致了 manifest文件中記錄的版本號和實際庫的版本號不一致(程序要求它們的版本號一致才能運行)。這個版本的程序部署需要兩個步驟,首先要使 manifest文件中依賴項的版本號與實際庫的版本號一致,均為9.0.30729.1,方法是在工程設置中增加一個宏定義 _BIND_TO_CURRENT_VCLIBS_VERSION,該宏定義於C:\Program Files\Microsoft Visual Studio 9.0\VC\include\crtassem.h文件中,然后重新編譯程序。接下來還是將VC安裝目錄下的redist目錄(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的庫以及對應的manifest文件拷貝到執行程序同目錄下,然后修改manifest文件中依賴項的版本號為 9.0.21022.8,這樣使得程序誤以為該目錄下庫的版本號為9.0.21022.8(實際上是9.0.30729.1版本),這樣程序到任何機器上都能夠正常運行了。

3、打過SP1補丁與SP1 ATL 安全更新 (KB973675)的VS2008

這是最新的更新。在SP1補丁之后,微軟又於近日發布了一個用於智能設備的 Microsoft Visual Studio 2008 Service Pack 1 ATL 安全更新 (KB973675),該補丁又將CRT/MFC/ATL庫的版本號升級,為9.0.30729.4148,這次升級比較好,manifest文件與庫的版本號一致了,不像 SP1一樣升級的不徹底。這樣只需要在工程設置中增加一個宏定義_BIND_TO_CURRENT_VCLIBS_VERSION,接下來重新編譯程序,然后直接把VC安裝目錄下的redist目錄中需要的庫以及對應的manifest文件拷貝到執行程序同目錄下,這樣程序到任何機器上都能夠正常運行了。

順便提一下,如果不想在發布程序時帶上這些庫和manifest文件(如果沒有必要的話),那么可以采用靜態編譯CRT和MFC,然后把manifest文件添加到資源中,這樣編譯出的程序只要一個exe就可以在任何機器上直接運行了。

參考文章:

1、“應用程序配置不正確,程序無法啟動”的解決方法資料收集:http://hi.baidu.com/fairysky/blog/item/e7a8366dbaa735f3431694c8.html

有的時候,你在Visual C++上面經過好幾個月的辛勤努力,終於將程序編寫完成並且測試完畢,然而當你試圖在客戶的發布機上運行剛寫好的程序時,有可能會碰到類似下面的錯誤,操作系統告訴你“由於應用程序配置不正確,應用程序未能啟動。重新安裝應用程序可能會糾正這個問題”:

VS2008編譯的程序在某些機器上運行提示“由於應用程序配置不正確,應用程序未能啟動”的問題 - tangxingqt - doomgnu的博客

一般情況下,這個問題都是由於程序不能找到所需要的C運行庫(CRT)而引起的。

在Windows XP SP2以后,Windows引入了Side-by-Side執行的概念,這個概念本來是.NET提出來的,但是Windows后來將這個概念集成到操作系統層面上來了。大家都應該知道Dll Hell的問題,為了解決Dll Hell的問題,Side-By-Side提出不同版本的dll文件可以同時存在於同一個系統里面,而且依賴於不同版本dll的應用程序在運行的時候可以使用到它當初被編譯生成的dll。前面的話,有點繞,舉個例子:

1.         假定你編寫了一個C++程序A,是使用MFC 8.0(這個版本是隨着Visual Studio 2005)發布的。

2.         之后你的機器升級了Visual Studio的版本,從2005升級到2008,2008的MFC庫是9.0版本的,這個時候你的操作系統里面安裝了兩個版本的MFC,分別是8.0和9.0。

3.         你在Visual Studio 2008編寫了另外一個C++程序B,B依賴與MFC 9.0。

4.         如果你運行程序A的話,操作系統會將MFC 8.0加載到A的進程里面。

5.         如果你這時同時運行程序B,操作系統會將MFC 9.0加載到B的進程里面。這就是Side-by-side的執行概念。

操作系統之所以能夠這樣做,是因為它在加載程序A和B之前,除了查看PE格式里面A和B所依賴的Dll信息,都會查看A和B的manifest文件。Manifest文件保存了Windows可執行文件(包括exe和dll文件)要運行起來的環境設置信息,文件名一般是可執行文件的文件全名加上.manifest。例如notepad.exe的manifest文件就應該是notepad.exe.manifest。例外有的程序將 manifest文件直接嵌入到可執行文件的資源里面了,這也就是為什么有的時候你看不到程序的manifest文件的原因。通常來說,一個 manifest文件的內容如下(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>

上面的例子里面,就說明這個程序依賴於CRT 9.0,而且是調試版的,CPU架構是32位的CPU。對於將manifest文件嵌入到資源文件的程序我們也有辦法看到manifest的信息。

1.         一種是使用mt.exe(Visual Studio自帶的manifest處理程序):

mt -inputresource:test.exe;#1 /out:test.manifest

2.         另外一種是使用dumpbin程序將整個exe的內容打印到一個文件,然后用文本編輯器打開,搜索Assem字符串樣式就能找到manifest信息:

VS2008編譯的程序在某些機器上運行提示“由於應用程序配置不正確,應用程序未能啟動”的問題 - tangxingqt - doomgnu的博客 

解決方案

知道了程序依賴於具體哪一個dll以后,你可以將所依賴的dll拷貝到程序的安裝文件夾里面,以CRT庫綁定失敗為例,介紹解決步驟:

1.         從上例中我們知道程序依賴的Microsoft.VC90.DebugCRT庫,版本號是9.0.21022.8,需要32位機器版本的CRT。這個依賴項一般是因為你的程序是調試版,所以Visual Studio在編譯的時候,將調試版的CRT加入程序的依賴項。

2.         從Visual Studio的安裝文件夾里面將D:”Program Files”Microsoft Visual Studio 9.0″VC”redist”Debug_NonRedist”x86中的Microsoft.VC90.DebugCRT整個文件夾拷貝到應用程序所在的文件夾里面,注意:

a)         如果你的程序依賴的是32位的CRT,則要拷貝x86文件夾里面的Microsoft.VC90.DebugCRT文件夾,如果是先x64程序,則要拷貝x64文件夾里面。

b)         你需要確定Microsoft.VC90.DebugCRT文件夾里面的Microsoft.VC90.DebugCRT.manifest文件里面保存的版本信息而你程序依賴的版本信息匹配,Microsoft.VC90.DebugCRT.manifest里面的版本信息大版本號一定要一致,小版本號一定要等於或者大於你程序依賴的CRT的小版本號。比如上例中,我們的程序是依賴於CRT 9.0.21022.8,而我們的Microsoft.VC90.DebugCRT.manifest的版本是9.0.30729.1,這樣是可以的;而 8.0.30729.1就會有問題。如果大版本號一樣,小版本號不一致的話,一個比較簡單的方案就是修改程序的manifest文件,使其互相匹配就可以了。

3.         如果你的程序不是依賴調試版本的CRT,而是release版本的CRT,直接去微軟的官方網站下載一個crt redist包安裝上就可以了。

==============<>

如果你編譯了一個VC2008的默認的CRT/MFC的應用程序,如果目標部署電腦上沒有安裝相應的VC2008的動態庫,當運行你的程序的時個,會出現如下錯誤信息.

這是因為程序使用了基於VC2008的CRT/MFC的動態庫版本.

解決這個問題,有三種方法:

1.使用靜態鏈接庫編譯(缺點,生成的exe的程序過於龐大)

2.使用vcredist_x86.exe / vcredist_x64.exe 將VC2008的發行版的DLL安裝在你的系統上.(缺點,只能支持發行版,調試版程序不能支持)

3.將你的程序依賴的CRT/MFC的動態庫與你的程序一起發布(放在與你的發布程序同一目錄中)

 

第一種和第二種就不詳細講如何實現了,只要講第三種方法如何實現.優其是程序的開發是使用了VC2008 SP1的版本開發的程序.

 

在你的VC2008的安裝目錄下有兩個目錄,

  • C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.CRT
  • C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.MFC

只要將這兩個目錄下的文件一同拷貝到發布程序的同一目錄下:

  • Microsoft.VC90.CRT.manifest
  • msvcr90.dll
  • msvcp90.dll
  • msvcm90.dll
  • Microsoft.VC90.MFC.manifest
  • mfc90.dll
  • mfc90u.dll
  • mfcm90.dll
  • mfcm90u.dll

這些是這個程序依賴的發行版動態庫,同理,如果是調試版的發布程序,也一樣把相應的調試動態庫拷貝到相應目錄.

程序如你意運行起來了!

 

但是,如果你安裝的是VC2008 SP1的版本的時候,問題就來了,你的程序也一樣運行不起來了!

原因就是安裝了VC2008 SP1的時候,它把"VC/redist"用新的版本文件代替了,問題不大,但是,這個程序的版本是依賴於新的manifest的文件的,當你編譯VC2008-SP1的程序的時候,它同時把RTM-version寫入程序的manifest文件中,這個是舊的RTM-version,不與新版本的VC2008-SP1的"CRT/MFC"manifest版本一致,因此程序運行的時候是拒絕導入這些新的VC2008-SP1的CRT/MFC的運態庫!

 

解決方法有兩種.

 

方法一:

最簡單的,修改Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest文件,將新的版本號改為舊的版本號,如果是依賴其它的Microsoft.VC90.*.manifest的文件,也同樣是如此修改!

如果是裝了VC2008-SP1后,它的版本號是“9.0.30729.8″

未裝VC2008-SP1前的版本號為"9.0.21022.8"

過程如下:

將所依的動態庫的及它們的 manifest 文件拷貝到發布應用程序的同一目錄下,並修改Microsoft.VC90.*.manifest文件,將

version="9.0.30729.1"


修改為
version="9.0.21022.8"
恭喜你,你的程序運行起來了!

方法二
修改你的程序的所依賴的manifest,這樣程序會依整於新的manifest.
過程如下:
stdafx.h 這個文件中,增加如下宏定義:

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1
程序編譯后就會依賴於新的manifest,版本號為
"9.0.30729.1"

無須再修改manifest文件中的version版本號了.
將所依的動態庫的及它們的 manifest 文件拷貝到發布應用程序的同一目錄下
恭喜你,程序又運行起來了!

注意:如果你是想要新的MFC-feature-pack的功能,用這種方法是最好的.

注意一點,非常重要,如果已經安裝了vcredist_*.exe程序包,注意的是Dll會自動把引用調到系統目錄下的WinSxS目錄下的,即不再引用同一目錄下的動態庫!
如果是編譯時使用了(/clr)這個編譯選項去支持.net開發,你必須要安裝.net framework redistributable包!

不過,在2010,編譯的程序會不再需要manifest文件!
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

總結如下:

使用vs2008/vs2008開發的程序有2種部署方法:共享並行程序集和私有程序集部署方法

所謂的共享並行程序集部署方法是指程序依賴的CRT、MFC、ATL的DLL和manifest文件位於目標機器上的c:/windows/winsxs目錄中,發布程序的時候只需要將程序拷貝到目標機器上就可以了;私有程序集部署方法指的是發布程序程序的時候,將所依賴的crt、mfc、atl的dll放在程序的當前目錄下

 

對於release版程序

比較的簡單的方法是采用共享程序集的方式來部署,安裝vcredist.exe (Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)

也可以采用下面debug程序的私有程序集的部署方法

 

對於debug版本程序

◆ 若目標機器安裝了VS開發環境(vs2005 sp1/vs2008 sp1),則在機器上同時也安裝了共享並行程序集,包含各個版本的dll(8.0、9.0版本,位於C:/Windows/Winsxs目錄下),則不需做任何的部署,直接將需要發布的程序拷貝到目標機器上就可以了,這和release版程序的發布方式是一樣的

◆ 在沒有安裝VS開發環境(安裝了vs2005 sp1/vs2008 sp1)的機器上,只能采用私有程序集的方式來部署(因為vcredist.exe只安裝了release版的CRT、MFC、ATL的DLL和manifest文件,沒有對應的debug版本)

已知的2種方法:(針對vs2008 sp1,安裝了sp1之后,在系統上會存在兩個版本的CRT、MFC、ATL的DLL:9.0.21022.8和9.0.30729.1)

1、使當前程序的manifest文件中的依賴項的版本號與vc安裝目錄下的redist目錄下的dll的版本一致,均為9.0.30729.1

方法:

a、在編譯項目時定義一個符號_BIND_TO_CURRENT_VCLIBS_VERSION,該符號定義於C:/Program Files/Microsoft Visual Studio 9.0/VC/include/crtassem.h 文件中(假設VC安裝在c盤),這樣使得編譯后的程序的manifest依賴於CRT 9.0.30729.1版本(同樣的,對於MFC也應該定義一個類似的符號,大家可以自己在VC的include目錄下搜索“9.0.30729.1”或“9.0.21022.8”,就可以找到對應的定義該符號的頭文件)

b、通過外部工具修改生成的exe或dll中manifest文件(好像windows sdk中的mt.exe可以做到,不過關於這個工具的資料十分的少)

2、將VC安裝目錄下的redist目錄下(C:/Program Files/Microsoft Visual Studio 9.0/VC/redist)的Microsoft.VC90.CRT拷貝到要發布的程序的當前目錄下,修改Microsoft.VC90.CRT目錄中的Microsoft.VC90.CRT.manifest文件中的版本號,改成9.0.21022.8,這樣使得程序誤以為該目錄下的vc的dll版本是9.0.21022.8(實質上仍然是9.0.30729.1版本)



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM