VC 軟件發布的故事(1)
當我們興沖沖把自己寫的小程序傳給朋友,亦或是正式發布產品到用戶手中,時常會遇到“由于應用程序的配置不正確,應用程序未能啟動,重新安裝應用程序可能會糾正這個問題”。
這么個提示實在是讓人有點氣餒啊,那么怎么解決呢,是什么導致這個問題呢?
(注意,本文不涉及msvc7.x,因為這個版本的兩個主要產品我接觸很少)
首先,靜態鏈接所有庫是不會遇到這個問題的,但不是所有情況下我們都能靜態鏈接所有庫,特別是存在MFC擴展dll的時候,以及使用了沒有static lib的第三方庫的時候(這些庫可能要求動態鏈接msvcrt)。
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版本號的binary。
msvc9:取消定義 _BIND_TO_CURRENT_VCLIBS_VERSION 宏,這將編譯出使用msvc9 rtm版本號的binary。
這樣,使用標準的msvc8/msvc8sp1/msvc9/msvc9sp1 redist即可。
msvc10微軟取消了之前的設計,回歸了msvc6的做法,于是正確的發布應該是下面這樣
靜態鏈接:這個兼容問題最少,但是無法享受系統補丁帶來的安全和改進。
動態鏈接:可以依賴系統目錄下的msvcrt dll,這樣系統打補丁就會自動享受系統更新帶來的改進。也可以把msvcrt和自己的binary放在一起,這樣便享受不到系統更新。
補充說明:有極少數用戶報告即便拷貝msvcrt100.dll之類的文件到系統目錄或者binary目錄,也無法運行,我無法重現,不知道具體原因。

浙公網安備 33010602011771號