当咱们兴冲冲把本身写的小程序传给朋友,亦或是正式发布产品到用户手中,时常会遇到“因为应用程序的配置不正确,应用程序未能启动,从新安装应用程序可能会纠正这个问题”。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目录,也没法运行,我没法重现,不知道具体缘由。