超級總結:vs2008/2005 sp1 C++ 發佈程序 .

最近在新裝的Win7上 編譯/ 運行自己的 camera_work_simultaneously.exe 程序時,發現release 編譯/運行 沒有問題,但是Debug版本編譯通過,run時報錯:“The application was unable to start correctly(0x0000006). ....”

 再查看系統的event,

把在筆記本上用VC9.0發佈的SCCT.exe文件拷貝到 裝有Win7的 臺式機BV5上進行驗證,也是出同樣的問題!就是調用GigEVisionSdkD.dll時依賴的GenApi_MDd_VC80.dll又依賴與Microsoft.VC80.DebugCRT的運行時庫,最後沒有找到Microsoft.VC80.DebugCRT。

 於是進行下列步驟:

C:\Users\BV5\Desktop\SCCT\Debug  

      |--scct.exe

      |--opencv_calib3d231d.dll

      |--opencv_core231d.dll

                         .                    .

                         .    

      |--GigEVisionSdkD.dll

      |--GenApi_MDd_VC80.dll

      |--GCBase_MDd_VC80.dll

     (Microsoft.VC90.DebugCRT下的dll放到SCCT\下)

       |--Microsoft.VC90.DebugCRT.manifest

       |--msvcm90d.dll

       |--msvcp90d.dll

       |--msvcr90d.dll

       |--GenICam\bin\Win32_i86\GenApi\Generic

                                                                                  |--XMLLoader_MDd_VC80.dll

                                                                                  |--xerces-c_2_7.dll

                                                                                  |--Xalan-C_1_10.dll

                                                                                  |--XalanMessages_1_10.dll

GigEVision的在SCCT\下的目錄結構參考 “發佈帶GigEVision的程序 http://blog.csdn.net/jtop0/article/details/6934210

1、在Win7上(也就是 Winsxs目錄下)沒有Microsoft.VC80.DebugCRT 運行時庫? (的確

雖然

2、下載到Microsoft.VC80.DebugCRT 庫 版本8.0.50727.762, 並分別放到應用程序目錄SCCT\下 和 SCCT\GenICam\bin\Win32_i86\GenApi\Generic下(因爲running時,啓動camera要調用XMLLoader_MDd_VC80.dll,這個dll 又依賴於Microsoft.VC80.DebugCRT庫, 當然如果能找到msi文件的Microsoft.VC80.DebugCRT直接安裝到Winsxs目錄下,就可以共用了,不用再把運行時庫拷到SCCT\目錄下了

                     .

                     .

     |--GCBase_MDd_VC80.dll

    ( Microsoft.VC90.DebugCRT運行時庫 )

      |--Microsoft.VC90.DebugCRT.manifest

      |--msvcm90d.dll

      |--msvcp90d.dll

      |--msvcr90d.dll

    ( Microsoft.VC80.DebugCRT運行時庫 )

      |--Microsoft.VC80.DebugCRT.manifest

      |--msvcm80d.dll

      |--msvcp80d.dll

      |--msvcr80d.dll

       |--GenICam\bin\Win32_i86\GenApi\Generic

                                                                                  |--XMLLoader_MDd_VC80.dll

                                                                                  |--xerces-c_2_7.dll

                                                                                  |--Xalan-C_1_10.dll

                                                                                  |--XalanMessages_1_10.dll

                                                                                  |--Microsoft.VC80.DebugCRT.manifest

                                                                                  |--msvcm80d.dll

                                                                                  |--msvcp80d.dll

                                                                                  |--msvcr80d.dll

 

並且修改Microsoft.VC80.DebugCRT.manifest把版本號改爲8.0.50608.0GCBase_MDd_VC80.dll、GenApi_MDd_VC80.dll中嵌入的manifest 版本一致

當然Microsoft.VC90.DebugCRT.manifest中的版本號,也應該改爲 9.0.21022.8與嵌入scct.exe、GigEVisionSdkD.dll的manifest要求的版本一致

3、把機器上的目錄C:\Program Files\MaxxVision\GigEVision改爲C:\Program Files\MaxxVision\GigEVision1 以便運行scct.exe時,避免用系統中的GigEVision庫,而使用SCCT\目錄下的GigEVision庫以及GenApi_MDd_VC80.dll、GCBase_MDd_VC80.dll等。

4、再次運行scct.exe程序OK!

 

實際上這個問題根本上還是涉及到  vs2008/2005 sp1 C++ 發佈程序的問題!

先參考我的前一篇blogvs2008 sp1 C++ 發佈程序

 

現在對這個發佈 作一個全方位的總結: 

一、使用vs2008/vs2008開發的程序有2種部署方法:

靜態鏈接發佈:只要擁有程序的所有源代碼(包括庫),你就可以採用靜態鏈接到crt 和 MFC,來發布程序,運行時 只要一個exe文件就可以了,只不文件體積太大了點。

動態鏈接發佈:編譯程序時, 採用動態鏈接 運行時庫,即在project property---C/C++---Code Generation---Runtime Library 選 /MDd,發佈的exe應用程序還要附帶Runtime Library (dll) 程序才能運行(常用的方法)。

                         |-----------並行程序集 部署方法

                         |-----------私有程序集 部署方法

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

 靜態鏈接發佈

動態鏈接發佈

               |----並行程序集 法 (3 種方法

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

                             2 |-----安裝vcredist.exe (Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)

                             3 |-----用vs2008 的Redistibutable Merge Modules 去install 特定的VC++庫,(即用vs2008新建一個Setup and Deployment 的項目包含exe需要的運行庫,當install時就把相關的運行時庫自動放到winsxs中去了 )

 

                |----私有程序集法 (1 種方法 2 steps

                              step1|-----拷貝C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86目錄下的文件夾“Microsoft.VC90.CRT”下的4個文件到 應用程序文件夾下如:SCCT\

                                                                                                                    |--Microsoft.VC90.CRT.manifest

                                                                                                                    |--msvcm90.dll

                                                                                                                    |--msvcp90.dll

                                                                                                                    |--msvcr90.dll

                              step2|-----  並且修改 application.exe 和 Microsoft.VC90.CRT.manifest 中各自的manifest 描述 運行時庫版本不一致問題(只在安裝了vs2005 sp1/vs2008 sp1後纔會出現),(有2類方法)

                                                                 1|--------修改application.exe 中manifest描述的運行時庫版本號 9.0.21022.8 與 實際compile 時採用的運行時庫版本號(Microsoft.VC90.DebugCRT.manifest中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版本

                                                                                b|------(嵌入manifest)通過外部工具修改生成的exe或dll中manifest文件(vc2008 打開application.exe 雙擊在RT_MANIFEST下的"1" ,或者“記事本”打開application.exe修改版本號 好像windows sdk中的mt.exe也可以做到)

                                                                                c|------(未嵌入manifest)通過“記事本”打開application.exe.manifest文件修改

                                                                  2|---------修改實際compile 時採用的運行時庫版本號9.0.30729.1(描述在Microsoft.VC90.CRT.manifest中)爲  application.exe 中manifest描述的運行時庫版本號9.0.21022.8爲號一致 .即:用“記事本”在step1的application.exe所在目錄中把Microsoft.VC90.CRT.manifest文件描述的版本號9.0.30729.1改爲9.0.21022.8

          以上爲Release版本的發佈方法。Debug版本的application.exe 發佈 上面 |----並行程序集 法 (3種方法)的第2中方法行不通。因爲vcredist.exe只安裝了release版的CRT、MFC、ATL的DLL和manifest文件,沒有對應的debug版本。

          vc2005 sp1 版本號是:  8.0.50727.726      對應的RTM   版本號是:8.0.50608.0  

         

二、 關於 私有程序集 法 的說明:

1、只有在從未安裝過Microsoft.VC90.CRT運行時庫的機器中(也就是winsxs文件夾下沒有相應的Microsoft.VC90.CRT庫),私有程序集法才真正起作用,也就是 application.exe文件調用 當前文件夾下(私有發佈的)Microsoft.VC90.CRT 運行時庫。

2、如果機器中已經安裝了Microsoft.VC90.CRT(也就是winsxs文件夾下能找到),則 當運行application.exe時 首先調用 系統的(winsxs文件夾下)Microsoft.VC90.CRT運行時庫,不會調用私有的Microsoft.VC90.CRT運行時庫。

3、如果系統中安裝的Microsoft.VC90.CRT運行時庫有錯誤,則應用程序不能運行,回報錯,也不會調用私有的Microsoft.VC90.CRT運行時庫。唯一的解決方法就是 重新install 運行時庫。

4、要想強制應用程序application.exe調用 當前文件夾下(私有發佈的)Microsoft.VC90.CRT 運行時庫,而不管系統有無運行時庫,要同時去掉application.exe 和

Microsoft.VC90.CRT.manifest 中的“publicKeyToken” 屬性,詳見How to bypass the WinSxS for CRT/MFC/ATL DLLs:

 

If a DLL is installed in the WinSxS folder, the local DLLs will be ignored. So, if you want to be independed from global DLLs,  a method is :just remove the “publicKeyToken” attribute from the manifests!

So an application manifest looks like:

Application.exe.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.50727.42" processorArchitecture="x86" /> </dependentAssembly> </dependency> </assembly>

You must also set the correct verion-number of the DLL! And remove the “publicKeyToken” attribute.
The manifest the for DLL looks like:

Microsoft.VC80.CRT.Manifest:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86"></assemblyIdentity> <file name="msvcr80.dll"></file> <file name="msvcp80.dll"></file> <file name="msvcm80.dll"></file> </assembly>

Now the CRT DLLs in the WinSxS will be ignored and only the local DLLs will be loaded.

三、side-by-side assembly方法是MS 沒有用註冊表來進行的運行庫控制,

--------僅僅在Windows XP後的版本纔有這個特性

-------VC2005和VC2008採用了具有C runtime libraries 的 SxS

-------而VC2010中已經放棄這中方法,而是直接在dll文件後加一個版本號,用同名的dll 只要版本號不同,以後也視爲兩個dll。 如 msvcr100.v1.dll

要裝載Win32本地 的運行時庫到winsxs下,只有通過MSI(the Windows Installer)或第三方專用工具如InstallMate 7纔可以, .不能手動加入。

 

參考鏈接:

微軟的Dll管理方案及其變遷(Side-by-side assembly)http://www.cnblogs.com/zhihuichien/archive/2011/03/24/1993447.html

關於vc2005的找不到MSVCR80.dll的執行錯誤http://blog.csdn.net/lionzl/article/details/6015394

關於manifest,這個文章最detailhttp://blog.csdn.net/fuzb/article/details/6730826

How to bypass the WinSxS for CRT/MFC/ATL DLLshttp://blog.kalmbachnet.de/?postid=80

Vista & Windows Side by Side Assemblieshttp://kartones.net/blogs/kartones/archive/2007/05/01/vista-windows-side-by-side-assemblies.aspx

如何:部署“安裝和部署項目”http://msdn.microsoft.com/zh-cn/library/ms235317(v=VS.90).aspx

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/951fad2d-3e0a-4342-96a7-6aa318c90caa/

SxsTrace程序追蹤工具介紹及其使用http://www.sunchis.com/html/hsware/software/2010/0821/199.html

Using Windows side-by-side assemblieshttp://www.tarma.com/support/im7/kb/kb50036.htm

發佈了35 篇原創文章 · 獲贊 12 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章