當咱們興沖沖把本身寫的小程序傳給朋友,亦或是正式發佈產品到用戶手中,時常會遇到「因爲應用程序的配置不正確,應用程序未能啓動,從新安裝應用程序可能會糾正這個問題」。redis
這麼個提示實在是讓人有點氣餒啊,那麼怎麼解決呢,是什麼致使這個問題呢?小程序
(注意,本文不涉及msvc7.x,由於這個版本的兩個主要產品我接觸不多)安全
首先,靜態連接全部庫是不會遇到這個問題的,但不是全部狀況下咱們都能靜態連接全部庫,特別是存在MFC擴展dll的時候,以及使用了沒有static lib的第三方庫的時候(這些庫可能要求動態連接msvcrt)。.net
msvc6時代沒這個問題,由於程序不能運行會提示缺乏xxx.dll,這樣很容易解決,只須要把必要的dll和軟件一塊兒發佈就能夠了(這個須要注意dll做者的再發布許可協議)。設計
msvc8,msvc9引入了所謂的程序集概念(注意不是.net那個意義的程序集,可是藉助於這個概念)使用winsxs來避免dll hell,可是(嗯,你們都怕這個可是)卻引入了另外一個問題:版本匹配。產品
假設下列場景:編譯
1 咱們編譯環境是msvc8或者msvc9,而且始終安裝最新的補丁擴展
2 發佈給用戶編譯出來的binary和msvc8/msvc8sp1/msvc9/msvc9sp1 redist軟件
3 運行失敗配置
這實在是使人倍感挫折,爲何不行了呢?問題的根源在menifest,若是咱們打開binary隨帶的menifest,而且檢查相關dll的版本號,會發現版本號遠高於msvc redist裏面的,這將致使系統拒絕加載dll,表面現象就是
「因爲應用程序的配置不正確,應用程序未能啓動,從新安裝應用程序可能會糾正這個問題」。
結論:編譯環境的補丁會將編譯環境的頭文件升級,致使默認配置編譯出來的binary需求更高級的版本號。
解決辦法:
msvc8:定義 _USE_RTM_VERSION 宏,這將強制編譯出使用msvc8 rtm版本號的bingary。
msvc9:取消定義 _BIND_TO_CURRENT_VCLIBS_VERSION 宏,這將編譯出使用msvc9 rtm版本號的bingary。
這樣,使用標準的msvc8/msvc8sp1/msvc9/msvc9sp1 redist便可。
msvc10微軟取消了以前的設計,迴歸了msvc6的作法,因而正確的發佈應該是下面這樣
靜態連接:這個兼容問題最少,可是沒法享受系統補丁帶來的安全和改進。
動態連接:能夠依賴系統目錄下的msvcrt dll,這樣系統打補丁就會自動享受系統更新帶來的改進。也能夠把msvcrt和本身的binary放在一塊兒,這樣便享受不到系統更新。
補充說明:有極少數用戶報告即使拷貝msvcrt100.dll之類的文件到系統目錄或者binary目錄,也沒法運行,我沒法重現,不知道具體緣由。