使用VS2008編譯了一個程式,使用到自己編譯的DLL,丢到某些機子上無法運作,提示“由于應用程式配置不正确,應用程式未能啟動”的錯誤,裝了vcredist_x86也沒有用,開始以為是DLL的問題,後來換個簡單的程式,仍然不行,百撕不得其解,後來上網找,下面有說了很多解決辦法。
我最終的解決辦法是複制本機中的.manifest檔案,修改裡面的版本号,複制到提示錯誤的機子上,與可執行程式放在同一目錄就可以了。在計算機中管理的系統工具,事件檢視器可以檢視應用程式的消息,找到“由于應用程式配置不正确,應用程式未能啟動”相關的錯誤,有那個版本号。

修改.manifest檔案中version的版本号:
<assemblyIdentity type="win32" name="Microsoft.VC90.MFC" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
根據事件檢視器裡面的資訊看支援的版本是哪個,對應修改即可(有好多.manifest檔案,不記得具體是哪個了),下面的文章有詳細的說明~~~
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、“應用程式配置不正确,程式無法啟動”的解決方法資料收集:
有的時候,你在Visual C++上面經過好幾個月的辛勤努力,終于将程式編寫完成并且測試完畢,然而當你試圖在客戶的釋出機上運作剛寫好的程式時,有可能會碰到類似下面的錯誤,操 作系統告訴你“由于應用程式配置不正确,應用程式未能啟動。重新安裝應用程式可能會糾正這個問題”.
一般情況下,這個問題都是由于程式不能找到所需要的C運作庫(CRT)而引起的。
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資訊:
解決方案
知道了程式依賴于具體哪一個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包安裝上就可以了。
附:解決方案參考:
方案一:
方法一:
在C:\Program Files\Microsoft Visual Studio 8\VC\redi
st\Debug_NonRedist\x86 \Microsoft.VC80.DebugCRT 下找到了下列檔案:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest
把這幾個檔案拷貝到目标機器上,與運作程式同一檔案夾或放到system32下,就可以運作那個程式了。
其他release版,MFC程式什麼的都是拷redist下相應檔案夾下的檔案就可以了,檔案夾後都有辨別!
方法二:
修改編譯選項,将/MD或/MDd 改為 /MT或/MTd,這樣就實作了對VC運作時庫的靜态連結,在運作時就不再需要VC的dll了。
方法三:
工程-》屬性-》配置屬性-》正常-》MFC的使用,選擇"在靜态庫 中使用mfc"
這樣生成的exe檔案應該就可以在其他機器上跑了。
方法四:
你的vc8安裝盤上找到再分發包vcredist_xxx.exe和你的程式捆綁安裝
我逐一測試下來,直到第三個方法才成功.第二個方法不知道在哪裡修改編譯選項是以放棄了,第四個方法不喜歡,這跟直接安裝.net framework 2.0 有什麼差別嗎?還不如直接安裝.net framework 2.0 呢.
方案二:
最早出現這個錯誤我和許多人認為的一樣
認為是缺乏DLL庫檔案導緻.但是在測試機複制了DLL甚至安裝了.net framework 2.0以後
都無法解決問題,最後确認不是由缺乏DLL所緻
因為程式是純win32的應用程,非托管代碼,是以也無需.net framework
Visual C++2003/2005預設的MFC程式是使用動态MFC庫(Use MFC in a Shared DLL)來連結的
而動态MFC庫使用 的是Multi-threaded DLL (/MD)
由于XP對于PE檔案格式監測更加嚴格.
就會導緻部分使用多線程DLL的可執 行檔案在調用的時候出錯
修改項目屬性的編譯開關
Project->Property->configuration Properties->C/C++->Code Generation->Runtime Library
修改成 Multi-threaded (/MT)
修改了Runtime類型以後
需要将MFC的編譯類型也改成靜态庫
Project->Property->configuration Properties->General->Use of MFC
修改成Use MFC in a Static Library
一部分情況下在這步就能解決問題
另外一部分情況會遇見如下情況
編譯器報錯
CODE:
nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj)
[Copy to clipboard]
産生這個問題的原因是庫依 賴關系
在Project->Property->configuration Properties->Linker->Command Line
加入編譯開關/verbose:lib可以顯示詳細的庫連結順 序
------ Build started: Project: PerfMonDemo, Configuration: Release Win32 ------
Linking...
Searching libraries
Searching d:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\lib\pdh.lib:
Searching d:\Program Files\Microsoft Visual Studio 8\VC\lib\DelayImp.lib:
.................
Searching d:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\lib\nafxcw.lib:
Finished searching libraries
.\Release/PerfMonDemo.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at "file://d:\Dev\Performance Monitor\Release\BuildLog.htm"
PerfMonDemo - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
我 們發現在libcpmt.lib聲明過的operator new在nafxcw.lib中再次定義
解決方法如下
Project->Property->configuration Properties->Linker->Input->Additional Dependencies
加入
nafxcw.lib
libcpmt.lib
Project->Property->configuration Properties->Linker->Input->Ignore Specific Library
這樣連結程式就不會先按照預設順序來連接配接這兩個庫檔案
而是在最後在加入對他們的引用.這樣就避免了 這個問題
下面是一張可能發生沖突的清單
若要使用此運作時庫 請忽略這些庫
單線程 (libc.lib) libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
多線程 (libcmt.lib) libc.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
使 用 DLL 的多線程 (msvcrt.lib) libc.lib、libcmt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib
調試單線程 (libcd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcmtd.lib、msvcrtd.lib
調 試多線程 (libcmtd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、msvcrtd.lib
使 用 DLL 的調試多線程 (msvcrtd.lib) libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib
這裡還有一篇
<a href="http://blog.csdn.net/feng_enlove/article/details/5917903">vs2008釋出c編寫的dll程式 初始化失敗-0xc0150002</a>
用VC2005編譯的程式,編譯時沒有任何錯誤,但是運作時就是提示“應用程式正常初始化失敗”!! 查找了各方面資料,做了各種嘗試,網上說什麼的都有:有讓安裝vc2005 sp1更新檔的;有讓安裝vcredist_x86.exe的; 有讓把CRT庫的dll直接拷貝到程式目錄的; 有讓清理系統資料庫的;有讓裝.NetFramework新版本的;有讓查manifest的;
結果我嘗試了半天,幾乎都是浪費時間。上面最後一條說的還算正确,隻是作者把事情描述得太繁瑣了。。現在把處理的方法說一下,省得大家再走彎路:
1. VC2003、VC2005、VC2008及其後續版本,對底層最基本的CRT、MFC、ATL庫都進行了重構,為了避免不同版本的庫引起沖突,重構後的庫檔案一般放在 C://windows/WinSxS 檔案夾中,并用特定的檔案夾/檔案名稱進行辨別;
2. 與VC6不同, VC2003、VC2005、VC2008及其後續版本,引入了manifest清單的概念,即應用程式編譯後會同時生成對應的.manifest檔案,并将該.manifest檔案作為資源編譯到dll或者exe中去。.manifest檔案實際上是一個XML格式的文本檔案,裡面記錄了dll或exe中要引用的CRT、MFC、ATL庫的版本和名稱。VC6編譯的應用程式對CRT、MFC、ATL的dll都是直接調用,而VC2003、VC2005、VC2008編譯的程式都是先查詢編譯到資源中的manifest中的記錄,然後按照記錄提供的版本和名稱去搜尋對應的CRT、MFC、ATL庫以及随庫釋出的.manifest檔案,搜尋的路徑包括目前目錄、C://windows/WinSxS 等等,如果沒有找到對應的庫檔案,則提示“應用程式正常初始化失敗”;
3.是以解決這個問題的辦法就是:(a)用文本編輯器打開exe或dll對應的.manifest檔案,檢視它引用的CRT、MFC、ATL庫的版本;或者,用UltraEdit直接打開exe或者dll,從資源區中找到編譯進去的.manifest資訊,找到它引用的CRT、MFC、ATL庫的版本;或者,運作程式,當程式彈出“應用程式正常初始化失敗”對話框時,在桌面上右鍵點選“我的電腦”-“管理”-“事件檢視器”-“系統”,輕按兩下檢視其中的記錄,可以看到出錯的原因是因為缺少了某某版本的CRT、MFC、ATL庫,記錄下這個版本資訊;(b)記錄到的庫的版本資訊一般類似于“Microsoft.VC90.DebugCRT”,之後到C://windows/WinSxS 或者VC200X的安裝檔案夾中搜尋包含這個字元串的檔案夾和檔案,将搜尋到的dll和.manifest檔案都拷貝到應用程式所在的檔案夾中,其中,.manifest檔案必須重命名為“Microsoft.VC90.DebugCRT.manifest”(這裡以Microsoft.VC90.DebugCRT為例),這樣應用程式就可以正常運作了;(c)注意:庫的.manifest檔案和dll要一同拷貝到應用程式根目錄去,因為應用程式會将編譯到内部的manifest資訊與外部的.manifest檔案進行對比,之後才會對庫的dll進行調用。如果隻拷貝庫的dll檔案是沒有用的;
4.如果本機編譯和運作程式都ok,但是将編譯好的程式拿到其它機器上确無法運作,則多半也是這個原因。另外,如果提示"應用程式配置不正确",大多也是因為上面所說的CRT、MFC、ATL庫版本與應用程式不比對導緻的,可以如法炮制進行解決;
把VS安裝目錄下的Microsoft Visual Studio 9.0/VC/redist/Debug_NonRedist/x86/Microsoft.VC90.DebugCRT下的
msvcm90d.dll
msvcp90d.dll
msvcr90d.dll
Microsoft.VC90.DebugCRT.manifest
這幾個檔案複制到應用程式安裝後的根目錄下(注:我裝的是VS2008,如果是VS2005的話上面的90的地方全部換80),原因就是我的程式裡依賴了VS裡面的一些庫,是以不裝VS的機器上會找不到相應的dll。把這幾個dll釋出時一起釋出就好了。
但是這樣之後,出現了另一個問題,提示“應用程式正常初始化失敗”,無奈繼續求助百度GOOGLE兩位大神,一查發現自己中了大獎,号稱VS釋出程式的兩大難題讓我一次全遇到了。
不斷翻啊翻,翻到http://bbs.17173.com/topics/4550/200907/21/1852512,1.html?time=1248186834這個網頁的時候,裡面的第一種方法提醒了我,嘗試了下,還不行,突然想起,我用的是VS2008,他提供的是2005的下載下傳位址,于是按照那個名字複制的2008的,下載下傳安裝之,問題最終解決。
下載下傳的軟體名字為Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) 。
Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) 會為 Visual C++ 庫安裝必要的運作時元件,使使用者能夠在未安裝 Visual C++ 2008 SP1 的計算機上運作使用 Visual C++ SP1 開發的應用程式。
提供一個下載下傳位址,微軟的官方下載下傳,速度還可以:
http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=a5c84275-3b97-4ab7-a40d-3802b2af5fc2
同時提供另一個對此問題講解比較透徹的網址:http://hi.baidu.com/kidcdf/blog/item/aad99901207fe1d2267fb5da.html
OK,這樣就可以把使用VS2008編寫的程式運作在未裝VS的機器上了。
最後再轉一篇
再談VC2005 釋出程式的兩大問題:"應用程式正常初始化失敗","應用程式配置不正确",攻略全
2008年01月31日 星期四 23:29
自己電腦上能用,到了其他電腦上就不能用了,是不是很頭痛,除了必要的DLL檔案,還有些什麼是必須一起打包發行的呢?
1."應用程式配置不正确"
1.如果你的項目屬性是 MD 或 MDd,那就要把以下檔案放入你的EXE目錄一起釋出
開始-運作- X:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT
2.如果你想靜态編譯進EXE,也就是 MT/MTd,那就參看這裡:建議動态連結,這種不同開關的LIB也能一起工作了.
C Runtime Library:
開關
對應的庫
版本
/MD
MSVCRT.LIB
多線程DLL的Release版本
/MDd
MSVCRTD.LIB
多線程DLL的Debug版本
/MT
LIBCMT.LIB
多線程靜态連結的Release版本
/MTd
LIBCMTD.LIB
多線程靜态連結的Debug版本
/clr
MSVCMRT.LIB
托管代碼和非托管代碼混合
/clr:pure
MSVCURT.LIB
純托管代碼
C++ Standard Library:
MSVCPRT.LIB
MSVCPRTD.LIB
LIBCPMT.LIB
LIBCPMTD.LIB
在項目屬性-連結-輸入 中,輸入對應的庫,記住程式裡還要還引用其他LIB,其他LIB也必須是相同的開關,比如都是 /MTD
2.應用程式正常初始化失敗:
1.今天這兩種情況都被我碰到了,這個比較好解決,在Microsoft Visual Studio 8檔案夾内搜尋
vcredist_x86.exe VC可再發行包,到目标機器上安裝一下,不用重新開機,即可使用.
2.項目的檔案被放在了fat/fat32分區上導緻的, 解決方法是把它們都移動到ntfs分區上, 或者把“項目屬性|Manifest Tool|General|Use FAT32 Work-around”設為yes。
3.如果把相應的MFCDLL全COPY過去了,還不行怎麼辦呢?
(1)用ultraedit,editplus打開你的EXE檔案,搜尋manifest,找到使用的DLL版本号,如version="8.0.50.XXX"
(2)DEBUG模式下報此錯的話, 把你電腦上的 c:\windows\winsxs\policies\x86_policy.8.0.Microsoft.VC80.DEBUGCRT.XXXXXXXXXXX
找到對應版本号的cat,和policy這兩個檔案,再找到
c:\windows\winsxs\manifest\x86_Microsoft.VC80.DebugCRT_XXXX_8.0.50727.762_XXXXX.cat和x86_Microsoft.VC80.DebugCRT_XXXXXX_8.0.50727.762_XXXXX.manifest
複制到出問題的機子上的對應目錄就OK了
3.缺少SP1更新檔,
GHOST了C槽後,發覺再運作OGRE的程式就不行了,:"應用程式正常初始化失敗",調試器輸出:
LDR: LdrpWalkImportDescriptor() failed to probe d:\program\project\BumperCar\BumperCar\Debug\exe\OgreMain_d.dll for its manifest, ntstatus 0xc0150002 ,想起來了,VC2005要裝SP1才相容OGRE1.4X,這裡放出更新檔.
英文更新檔 431M
http://download.microsoft.com/download/6/3/c/63c69e5d-74c9-48ea-b905-30ac3831f288/VS80sp1-KB926601-X86-ENU.exe
中文更新檔
http://download.microsoft.com/download/8/0/7/8071514d-9370-45c3-8af1-4ff09a70e59d/VS80sp1-KB926604-X86-CHS.exe