问题描述:

用VS2013写好一个程序,在本机上运行一切正常。但是如果直接把exe文件放到另一台机器上用,则会出现:

Windows XP:不是一个正常的win32程序

Window 7:缺少msvcp120.dll

能否有一种方法,把程序运行所需要的环境一并打包,使之可以在任何Windows计算机上使用?

为了方便说明,我们新建一个简单的控制台应用项目,直接如图:

非常简单,一个使用了C++标准库的控制台应用程序,在装有开发环境的本机顺序执行出如下效果:

真实一个旷世奇作,我们迫不及待地就此发给XP老哥炫耀,万万没想到:

装逼不成反被XP老哥奚落:“负分滚粗!”

这里我们遇到了题目遇到的问题之一,确实叫人纳闷,不过随便搜索一下就会有解决方法:

是的,在项目配置属性中,将平台工具选择为“Visual Studio 2013 -Windows XP(v120_xp)”,即可解决“无效的Win32应用程序”问题。

但是我们还要知其然所以然,为什么?

项目默认的Visual Studio 2013(v120) 与 Visual Studio 2013 - Windows XP(v120_xp) 生成出来的可执行文件有何区别,以至于前者在XP上执行会出现那样的错误?

最直觉的方法自然是比较一下两版本执行文件的区别,我们选用PE(Portable Executable :32位或64位Windows操作系统使用的可执行程序或者动态链接库的文件格式)工具 Stud_PE 进行PE文件头结构比较,很容易看出区别:

看到打红叉的地方,就是两个文件不同之处,其它地方几乎没有区别。

关于PE文件结构是另外一个话题,我们暂不深入讨论。

单就这两处我们顾名思义一下就很容易明白:

MajorOSVersion,(目标)操作系统主版本号 ,选择默认平台工具集的文件的值是6,后者是5。

MinorOSVersion ,(目标)操作系统次版本号,前者是0,后者是1。

MajorSubsystemVersion,(目标)Win32子系统主版本号,前者是6,后者是5。

MinorSubsystemVersion,(目标)Win32子系统次版本号,前者是0,后者是1。

总结一下:一个是6.0,一个是5.1。

很明显5.1不就是XP的版本号么,6.0就是Vista呗?

我们是否可以认为,项目默认选择的“平台工具集”生成的可执行文件是不能在6.0以下版本的Windows运行的?

试验结果是:当我把6.0手动修改成5.1之后,这个文件立刻可以在XP里运行了,事实上,Major/MinorOSVersion的值似乎没有起到什么作用,仅仅修改XxxxxSubsystemVersion的值就可以保证程序顺利执行起来了。反之亦然。同时还发现:在XP中,改为5.1可以,5.2及更高就不行。

对于这个问题的认识虽然仍流于表面,但由于知识有限,我们就不再探究PE结构中的这几个值的深层次含义了。当然如有大牛指点一二就更好了。

现在好了!我们不但解决了XP的运行问题,还大致了解了问题的根源。那么让我们继续发布吧!

将新的、XP的、“5.1的”版本发给XP老哥:

我勒个去?你等等,我再编译一个release版本......试试:

擦?不是说好的“Release”吗?你等等,不就是一个dll文件吗,我这里有!我发给你......

我从自己的系统(Win 8.1 x64)C:\Wdinwos\system32 文件夹找一个MSVCP120.DLL发过去:

是啊,这不是逗呢?拿64位的dll文件去冒充32位的,能行?重新去VS目录扒一个正确的32位msvcp120.dll补上:

又来,这次叫做MSVCR120.dll ,不仔细看还真没认出来。继续补上:

呵呵呵呵呵,终于得以正确运行了,但是这么狼狈的炫耀怎么能让人高兴起来呢?

经过一番折腾,好歹知道了是因为缺少文件,那么下次发布程序把这些瓶瓶罐罐DDLL都带上打包不就行了吗?没错,确实是这么个道理,但总感觉很不专业的样子。

所以,一个正常的解决方案就是和其它答案中所说的那样,让目标机器安装VisualC++Redistributable Packages forVisualStudio2013

这个东西的作用就是:

安装运行使用 VisualStudio2013 生成的 C++ 应用程序时所需的运行时组件。

简单观察安装后XP系统中多出了哪些文件:

这样一看,“运行时组件”就变得直观和具体了。

它们都是什么呢?我们先去我们电脑VS的安装目录中看一下:

通过路径很容易理解,这是有关VC的redist(再发行)的东西,我们进x86看一下:

有关CRT(运行时库),MFC,MFCLOC(MFC的本地化文件)等等,我们看看CRT里面:

看到了眼熟的这两个dll了。实际上,你参考前面那个XP多出文件的图片,那些dll都能在这里找到。

这就是Visual C++ Redistributable 包括的东西,每个VS版本都不一样。VS2013对应的就是120

那管它是VS2013还是2012还是2008,对应的发行包给装上不就完了。

没错。但是我们还要继续研究一下,至少,研究一下如何让一个可执行文件“独立”运行在XP上。

回到项目配置,如下图:

我们看到,运行库这一项,包含4中选择。

发话不多说,我们简单粗暴干脆每一种都生成一个进行比较:

四种版本,分别起了对应的名称,多线程(MT)多线程DLL(MD)多线程调试(MTd),多线程调试DLL(MDd)

利用Stud_PE 观察比较它们的函数导入表,发现:

1、多线程DLL(MD)和多线程调试(MDd)

两者都导入了2个MSVCxxxx.dll(黄箭头所指),但细看又不同,调试版本(MDd)导入的是MSVCP120D.dll和MSVCR120D.dll,比非调试(MD)的那个都多一个字母'D'。很明显这是配套给调试版的运行时库。而我们之前安装的发行包所部署的都是不带D的版本,是给Release版的程序配套使用的。

顺便一提MSVCP代表MicroSoft Visual C++(Plus) ,MSVCR则代表MicroSoft Visual C(没有+)Runtime。 一个是C++运行时库一个是C运行时库

2、多线程(MT)与 多线程调试(MTd)

两者貌似一样,都没有MSVCP和MSVCR函数导入,只有Kernel32.dll。同时观察这两个文件的体积,都比MD或MDd大了很多,这正式它们不需要导入运行时库DLL函数的原因,因为它们把运行时库静态编译到自己的文件中去了。这也代表着它们运行的时候不会再依赖外部的运行时库DLL文件。

所以,想要你的exe独立运行在XP中:

1、将平台工具集选择为"Visual Studio 2013 - Windows XP (v120_xp)"。

2、将运行库选择为 【多线程 /MT 】或【多线程调试 /MTd】。

3、当然如果使用了MFC,同理的要设置【在静态库中使用MFC】:

转自《如何用 VS 2013 打包 VC++ 程序?》 Dr Yao的回答。

以上。

【转】如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件的更多相关文章

  1. [转]如何使用VS 2013發布一個可以在Windows XP中獨立運行的可執行文件

    https://read01.com/Mg337.html (台/湾的论坛,需要f/q) 1. 閱讀此文章的同學先看看我的另外一篇文章: 現在,我們深入探討一下: <如何使用VS 2013發布一 ...

  2. 如何成功发布一个MSMQ的Windows服务

    因为MSMQ的使用需要不断的查看队列是否有新消息,所以一般是结合Windows的服务,当然也可以用一个不关闭的Winform程序,不过前者更好一些,不怕被人误关. 完成MSMQ的WindowsServ ...

  3. 使用gitbook 发布一个教程文档网站

    gitbook是一个好用的发布电子书的项目:使用gitbook 可以在本地写好文档再远程推送到库:也可以在gitbook提供的在线平台上制作电子书:要想在自己的服务器上使用gitbook 发布一个网站 ...

  4. iis发布----在XP中发布高版本web遇到问题总结

    解决方法是之前在网上看到的,总结一下. 我在vs2010中做的web网页,放到XP系统中发布是遇到问题,XP中的iis版本是iis. 提示.net framework版本上的问题. 1.在网站属性中把 ...

  5. 用Visual Studio 2015 编译张帆的第一个NT式驱动,并且成功安装到Windows XP里面!!!

    开发工具:Visual Studio 2015 企业版 目 标 机:Windows XP X86 前提:我们已经成功安装了Visual Studio 2015以及WDK,而且更重要一点是一定要SDK版 ...

  6. Visual Studio 2013 发布正式版

    SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好? Visual Studio 2013 发布正式版及使用感受 (注意:文末我添加了一个小节,用来更新最新的一些使用感受.) ...

  7. Visual Studio 2013 发布正式版及使用感受

    (注意:文末我添加了一个小节,用来更新最新的一些使用感受.) 昨天晚上,微软在正式发布Windows 8.1的同时,也同时发布了Visual Studio 2013产品系列的正式版. 版本情况 Vis ...

  8. 【转】发布一个基于NGUI编写的UI框架

    发布一个基于NGUI编写的UI框架 1.加载,显示,隐藏,关闭页面,根据标示获得相应界面实例 2.提供界面显示隐藏动画接口 3.单独界面层级,Collider,背景管理 4.根据存储的导航信息完成界面 ...

  9. iphone开发之用lipo合并模拟器库和真机库,发布一个通用的静态库

    转载自:http://blog.csdn.net/arthurchenjs/article/details/6044616 lipo lipo –create Release-iphoneos/lib ...

随机推荐

  1. Jquery揭秘系列:Validation实现

    之前讲了一部分揭秘系列的东西,由于年初的时候在改项目,也没有写下去.现在开始闲下来了,会继续写没写完的东西,各种原生js实现Jquery的功能. 转入正题,说一下今天要讲的东西. 相信很多tx在项目里 ...

  2. 教你一招:根据身份证号计算出生年月和年龄 text函数和mid函数混用 datedif函数和today函数混用

    在电子表格Excel中,使用text函数和mid函数混用,根据身份证号计算出生年月: =text(mid(A2,,),"0!/00!/00") #0!/00!/00 为日期的格式# ...

  3. 解决:Cannot get http://gerrit.googlesource.com/git-repo/clone.bundle

    同步cm12.1初始化出现的问题: fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle fatal: err ...

  4. Thinking in java学习笔记之set

    Random rand = new Random(47); Set<Integer> set = new HashSet<Integer>(); for(int i=0;i&l ...

  5. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  6. svn清理失败且路径显示乱码

    1.下载 sqlite数据库工具,sqlite3.exe下载地址:sqlite官网http://www.sqlite.org/download.html,我这里是windows操作系统,因此下载 Pr ...

  7. Mysql服务启动的时候 如何加载配置文件

    Mysql服务启动的时候 如何引导配置文件 (启动加载顺序)

  8. 2次使用fork避免产生僵尸进程和不去处理SIGCHLD信号

    1.如下代码所示 #include <unistd.h> #include <sys/types.h> #include <unistd.h> int main(i ...

  9. 框架集(Framesets)

    1.Frameset的使用 所谓框架便是网页画面分成几个框窗,同时取得多个 URL.只 要 <FRAMESET> <FRAME> 即可,而所有框架标记 要放在一个总起的 htm ...

  10. OSI参考模型及各层功能,TCP与UDP的区别

    OSI参考模型:ISO/IEC 7498标准定义了网络互联的7层结构模型,即开放系统互连参考模型. OSI参考模型定义了开放系统的层次结构.层次之间的相互关系,以及各层所包括的可能的服务.OSI的服务 ...