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版本号的bingary。

msvc9:取消定义 _BIND_TO_CURRENT_VCLIBS_VERSION 宏,这将编译出使用msvc9 rtm版本号的bingary。

这样,使用标准的msvc8/msvc8sp1/msvc9/msvc9sp1 redist即可。

msvc10微软取消了之前的设计,回归了msvc6的做法,于是正确的发布应该是下面这样

静态链接:这个兼容问题最少,但是无法享受系统补丁带来的安全和改进。

动态链接:可以依赖系统目录下的msvcrt dll,这样系统打补丁就会自动享受系统更新带来的改进。也可以把msvcrt和自己的binary放在一起,这样便享受不到系统更新。

补充说明:有极少数用户报告即便拷贝msvcrt100.dll之类的文件到系统目录或者binary目录,也无法运行,我无法重现,不知道具体原因。

posted @ 2015-01-17 21:48  Skogkatt  阅读(514)  评论(0编辑  收藏  举报