Win32主程序需要以下设置

第一步:在工程属性General设置

第二步:在C/C++ Code Generation 设置

第三步:SubSystem 和  Minimum Required Version 设置

如果Win32依赖一些额外的库,那些库也设置一下,防止程序运行失败

如何让VS2013编写的程序在XP下运行

作者:Dr Yao
链接:http://www.zhihu.com/question/25415940/answer/30803949
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

《如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件》。

这个问题是比较常见且容易造成初学者困惑的,作为曾经撞了无数次南墙的初级代码狗终于看到了自己能够回答的问题,那么就让我来简单阐述一下造成这个问题的简单原理极其简单解决方法,如有错误纰漏敬请指正。

/*我们讨论的是非托管的C++程序。*/

为了方便说明,我们新建一个简单的控制台应用程序项目,直接如图:
<img src="https://pic3.zhimg.com/c7153704844410ae49615ec1c65d0d9a_b.jpg" data-rawwidth="752" data-rawheight="322" class="origin_image zh-lightbox-thumb" width="752" data-original="https://pic3.zhimg.com/c7153704844410ae49615ec1c65d0d9a_r.jpg">
非常简单,一个使用了C++标准库的控制台应用程序,在装有开发环境的本机顺利执行出如下效果:
<img src="https://pic3.zhimg.com/2426de93b527e63dffee38e171743e76_b.jpg" data-rawwidth="328" data-rawheight="77" class="content_image" width="328">
真是一个旷世奇作,我们迫不及待地就此发给XP老哥炫耀,万万没想到:
<img src="https://pic3.zhimg.com/deacd686bad90b39eb4d60dbcf763ebe_b.jpg" data-rawwidth="598" data-rawheight="114" class="origin_image zh-lightbox-thumb" width="598" data-original="https://pic3.zhimg.com/deacd686bad90b39eb4d60dbcf763ebe_r.jpg">
装逼不成反被XP老哥奚落:“负分滚粗!”

这里我们遇到了题主遇到的问题之一,确实叫人纳闷,不过随便搜索一下就会有解决方法:
<img src="https://pic2.zhimg.com/84d9ea62473e9a5adb98d85484f752e5_b.jpg" data-rawwidth="768" data-rawheight="459" class="origin_image zh-lightbox-thumb" width="768" data-original="https://pic2.zhimg.com/84d9ea62473e9a5adb98d85484f752e5_r.jpg">
是的,在项目配置属性中,将平台工具集选择为"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文件头结构比较,很容易看到区别:
<img src="https://pic1.zhimg.com/f3eb98398207a712ffbdbbbf37cc8888_b.jpg" data-rawwidth="367" data-rawheight="384" class="content_image" width="367">
看到打红叉的地方,就是两个文件不同之处,其他地方几乎没有区别。
关于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老哥:
<img src="https://pic2.zhimg.com/0b00e7a38fa6242d89b1d691e26f12f1_b.jpg" data-rawwidth="588" data-rawheight="115" class="origin_image zh-lightbox-thumb" width="588" data-original="https://pic2.zhimg.com/0b00e7a38fa6242d89b1d691e26f12f1_r.jpg">
我勒个去?你等等,我再编译一个release版本…… 试试:
<img src="https://pic2.zhimg.com/3b1e351a004eef240a1422ccb55ad43d_b.jpg" data-rawwidth="580" data-rawheight="116" class="origin_image zh-lightbox-thumb" width="580" data-original="https://pic2.zhimg.com/3b1e351a004eef240a1422ccb55ad43d_r.jpg">
擦?不是说好的“Release"吗?你等等,不就是一个dll文件吗,我这里有!我发给你……
我从自己的系统(Win 8.1 x64)C:\Wdinwos\system32 文件夹找一个MSVCP120.DLL发过去:
<img src="https://pic4.zhimg.com/f44f4bbcea40797ace7637253dbb8047_b.jpg" data-rawwidth="652" data-rawheight="120" class="origin_image zh-lightbox-thumb" width="652" data-original="https://pic4.zhimg.com/f44f4bbcea40797ace7637253dbb8047_r.jpg">
是啊,这不是逗呢?拿64位的dll文件去冒充32位,能行? 重新去VS目录里扒一个正确的32位msvcp120.dll 补上:
<img src="https://pic3.zhimg.com/5ec316119d3f4c9dce3b570f58134e9e_b.jpg" data-rawwidth="589" data-rawheight="222" class="origin_image zh-lightbox-thumb" width="589" data-original="https://pic3.zhimg.com/5ec316119d3f4c9dce3b570f58134e9e_r.jpg">
又来,这次叫做MSVCR120.dll ,不仔细看还真没认出来。继续补上:
<img src="https://pic4.zhimg.com/73f1f261e22e08325c0b364c6a5ba66f_b.jpg" data-rawwidth="659" data-rawheight="310" class="origin_image zh-lightbox-thumb" width="659" data-original="https://pic4.zhimg.com/73f1f261e22e08325c0b364c6a5ba66f_r.jpg">
呵呵呵呵呵,终于得以正确运行了,但是这么狼狈的炫耀怎么能让人高兴起来呢?

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

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

这个东西的作用就是:

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

简单观察安装后系统中多出了哪些文件:
<img src="https://pic1.zhimg.com/23dcb90cde0a9c6a690a8f72635a3438_b.jpg" data-rawwidth="795" data-rawheight="605" class="origin_image zh-lightbox-thumb" width="795" data-original="https://pic1.zhimg.com/23dcb90cde0a9c6a690a8f72635a3438_r.jpg">
这样一看,“运行时组件”就变得直观和具体了。
它们都是什么呢?我们先去VS的安装目录中看一下:

<img src="https://pic3.zhimg.com/1a1d2b4c663e74736d57ed334a9e7082_b.jpg" data-rawwidth="622" data-rawheight="220" class="origin_image zh-lightbox-thumb" width="622" data-original="https://pic3.zhimg.com/1a1d2b4c663e74736d57ed334a9e7082_r.jpg">通过路径很容易理解,这是有关VC的redist(再发行)的东西,我们进x86看一下:通过路径很容易理解,这是有关VC的redist(再发行)的东西,我们进x86看一下:

<img src="https://pic3.zhimg.com/65356fdf2a2b16b56cccff01861ba352_b.jpg" data-rawwidth="568" data-rawheight="194" class="origin_image zh-lightbox-thumb" width="568" data-original="https://pic3.zhimg.com/65356fdf2a2b16b56cccff01861ba352_r.jpg">
有关CRT(运行时库),MFC,MFCLOC(MFC的本地化文件)等等,我们看看CRT里面:

<img src="https://pic3.zhimg.com/5112b3c6e7869e20d54cf4a3e0b7d06a_b.jpg" data-rawwidth="689" data-rawheight="156" class="origin_image zh-lightbox-thumb" width="689" data-original="https://pic3.zhimg.com/5112b3c6e7869e20d54cf4a3e0b7d06a_r.jpg">看到了眼熟的这两个dll了,实际上你参考前面那个XP多出文件的图片,那些dll都能在这里找到。看到了眼熟的这两个dll了,实际上你参考前面那个XP多出文件的图片,那些dll都能在这里找到。
这就是 Visual C++ Redistributable 包括的东西,每个VS版本都不一样。VS2013对应的就是120。

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

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

回到项目配置,如下图:
<img src="https://pic2.zhimg.com/70699c860bc9c1361ca732b24fa06c45_b.jpg" data-rawwidth="768" data-rawheight="459" class="origin_image zh-lightbox-thumb" width="768" data-original="https://pic2.zhimg.com/70699c860bc9c1361ca732b24fa06c45_r.jpg">
我们看到,运行库这一项,包含4种选择。
废话不多说,我们简单粗暴干脆每一种都生成一个进行比较:
<img src="https://pic1.zhimg.com/b666f08c3aa429b2052da512f3facd40_b.jpg" data-rawwidth="977" data-rawheight="759" class="origin_image zh-lightbox-thumb" width="977" data-original="https://pic1.zhimg.com/b666f08c3aa429b2052da512f3facd40_r.jpg">
四种版本,分别起了对应的名称,多线程(MT),多线程DLL(MD),多线程调试(MTd),多线程调试DLL(MDd)。
利用 Stud_PE 观察比较它们的 函数导入表 ,发现:
1. 多线程DLL (MD)和 多线程调试DLL (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】:
<img src="https://pic3.zhimg.com/e7a89c0ca62df994201337db4016099a_b.jpg" data-rawwidth="768" data-rawheight="459" class="origin_image zh-lightbox-thumb" width="768" data-original="https://pic3.zhimg.com/e7a89c0ca62df994201337db4016099a_r.jpg">

事情很简单,大致就是这样了

 
 
3.根据上面讲解自己写了一个Demo进行验证
1.MDD连接:以动态形式连接运行时库
 
 
然后在没有安装运行时库的虚拟机上运行:
 
MTd:
在虚拟机上运行:
 
release动态连接运行时库:
 
release静态连接运行时库:
注:曾经犯这样的错误,以为以MT/MTd方式编译,程序对所有的库都是静态链接的,其实错了,它只能决定运行时库是动态链接还是静态链接,对用户自己写的库或其他第三方库,其连接方式取决于代码(显式连接动态库Loadlibrary)或所提供的lib文件(为导入库还是静态库),移动程序到别的机器上时,还是要带上所需要的动态库的.
 
 
我自己的理解是,不管是第三方的静态库或者动态库连接运行时库的方式要和自己的程序连接运行时库的方式保持一致。

如何让VS2012编写的程序在XP下运行的更多相关文章

  1. (转载)用VS2012或VS2013在win7下编写的程序在XP下运行就出现“不是有效的win32应用程序“

    原文地址:http://www.vcerror.com/?p=1483 问题描述: 用VC2013编译了一个程序,在Windows 8.Windows 7(64位.32位)下都能正常运行.但在Win ...

  2. 如何让VS2013编写的程序在xp下运行

    总体分c++程序和c#程序 1.c++程序 这个用C++编写的程序可以经过设置后在XP下运行,主要的“平台工具集”里修改就可以. 额外说明:(1)程序必须为Dotnet 4.0及以下版本.(XP只支持 ...

  3. 用VS2012或VS2013在win7下编写的程序在XP下运行就出现“不是有效的win32应用程序

    经常创建项目的时候,采用空项目,那么编译成功后,最好修改下sbusystem . 链接器->系统->子系统->控制台或windows 后面的"最低版本"是5.01

  4. VS2010 和VS2012 的程序在XP上运行的方法

    问题表象: VS2012编译的程序不能再XP下运行 解决办法: 1.工程设置的方法 在vs2012里,右键 属性->配置属性-常规->平台工具集->选个VS2008什么的就ok了~ ...

  5. 让用VS2013编写的程序在XP中顺利运行

    vs2013编译好的exe文件拖到虚拟机xp中无法运行,提示错误,从网上搜索.找答案. 参考:http://blog.csdn.net/asanscape/article/details/387526 ...

  6. 使用Scala编写Spark程序求基站下移动用户停留时长TopN

    使用Scala编写Spark程序求基站下移动用户停留时长TopN 1. 需求:根据手机基站日志计算停留时长的TopN 我们的手机之所以能够实现移动通信,是因为在全国各地有许许多多的基站,只要手机一开机 ...

  7. VS2012 生成可以在XP下运行的exe文件

    1. 在已安装VS2012条件下,安装update,作者已经安装了update3; 2. 相关设置: 设置"平台工具集":在项目右击-属性-常规-在"平台工具集" ...

  8. 让用VS2012/VS2013编写的程序在XP中顺利运行

    转自:http://blog.csdn.net/asanscape/article/details/38752655/ 微软为了推销自家平台,默认配置下VS2012和VS2013编写的应用程序只能在V ...

  9. 让用VS2012/VS2013编写的程序在XP中顺利执行

    微软为了推销自家平台,默认配置下VS2012和VS2013编写的应用程序仅仅能在Vista/Win7/Win8上执行.但幸好还保留了生成XP程序的设置项.XP和Win2003的用户还是大量存在的,我们 ...

随机推荐

  1. BZOJ4856 病毒感染 [Jsoi2016] dp

    正解:区间dp+辅助dp 解题报告: 先放个传送门qwq 然后这题,又是一道看不懂题目的玩意儿:( 大概是语文太差 那就先解释下 其实只是一个点比较难明白就是它港 "假设JYY 进入i村庄并 ...

  2. git使用简单指南

    参考: https://www.fengerzh.com/git-reset/?utm_source=tool.lu git建库小结 (一)远端:1.在git网站上建设一个远程仓库复制git远程仓库地 ...

  3. ABAP抓取异常的方法:try,endtry

    部分转自:http://www.cnblogs.com/jiangzhengjun/p/4292428.html +4.Funcion函数异常处理 说明: 异常处理机制可以有效避免 dump发生, : ...

  4. [py][mx]django课程模型

    课程模型分析 分3个表 先设计课程表, 这是1 在设计lesson表,添加一个外键,course. 课程 1 course 章节 n lesson 视频 n video 资源 n coursereso ...

  5. 实习培训——Servlet(5)

    实习培训——Servlet(5) 1  Servlet 简介 Servlet 是什么? Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HT ...

  6. Ultra-QuickSort(poj 2299归并排序)

    http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=232#problem/A B - Ultra-QuickSort Time Li ...

  7. BGD-py实现学习【1】[转载]

    转自:https://github.com/icrtiou/Coursera-ML-AndrewNg 1.源码-对数据读取 import numpy as np import pandas as pd ...

  8. 机器学习理论基础学习15---条件随机场(CRF)

    一.CRF的由来HMM->MEMM->CRF 二.HMM到MEMM MEMM打破了HMM的观测条件独立假设 三.MEMM到CRF CRF克服了MEMM的label bias problem ...

  9. python-字符串前面添加u,r,b的含义

    u/U:表示unicode字符串 不是仅仅是针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码. 一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u:但是中文, ...

  10. MongoDB 工具助手类(.NET)

    在开发过程中,需要用到MongoDB,本身MongoDB自己对类的封装就特别好了.为了更加符合我们平时的开发使用,我现在进行了一个简单的封装操作. 连接数据库类:MongoDBContext usin ...