有的时候,你在Visual C++上面经过好几个月的辛勤努力,终于将程序编写完成并且测试完毕,然而当你试图在客户的发布机上运行刚写好的程序时,有可能会碰到类似下面的错误,操作系统告诉你“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”:

一般情况下,这个问题都是由于程序不能找到所需要的C运行库(CRT)而引起的。

在Windows XP SP2以后,Windows引入了Side-by-Side执行的概念,这个概念本来是.NET提出来的,但是Windows后来将这个概念集成到操作系统层面上来了。大家都应该知道Dll Hell的问题,为了解决Dll Hell的问题,Side-By-Side提出不同版本的dll文件可以同时存在于同一个系统里面,而且依赖于不同版本dll的应用程序在运行的时候可以使用到它当初被编译生成的dll。前面的话,有点绕,举个例子:

1.         假定你编写了一个C++程序A,是使用MFC 8.0(这个版本是随着Visual Studio 2005)发布的。

2.         之后你的机器升级了Visual Studio的版本,从2005升级到2008,2008的MFC库是9.0版本的,这个时候你的操作系统里面安装了两个版本的MFC,分别是8.0和9.0。

3.         你在Visual Studio 2008编写了另外一个C++程序B,B依赖与MFC 9.0。

4.         如果你运行程序A的话,操作系统会将MFC 8.0加载到A的进程里面。

5.         如果你这时同时运行程序B,操作系统会将MFC 9.0加载到B的进程里面。这就是Side-by-side的执行概念。

操作系统之所以能够这样做,是因为它在加载程序A和B之前,除了查看PE格式里面A和B所依赖的Dll信息,都会查看A和B的manifest文件。Manifest文件保存了Windows可执行文件(包括exe和dll文件)要运行起来的环境设置信息,文件名一般是可执行文件的文件全名加上.manifest。例如notepad.exe的manifest文件就应该是notepad.exe.manifest。例外有的程序将manifest文件直接嵌入到可执行文件的资源里面了,这也就是为什么有的时候你看不到程序的manifest文件的原因。通常来说,一个manifest文件的内容如下(test.exe.manifest文件):

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>

<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

<security>

<requestedPrivileges>

<requestedExecutionLevel level='asInvoker' uiAccess='false' />

</requestedPrivileges>

</security>

</trustInfo>

<dependency>

<dependentAssembly>

<assemblyIdentity type='win32' name='Microsoft.VC90.DebugCRT' version='9.0.21022.8'

processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />

</dependentAssembly>

</dependency>

</assembly>

上面的例子里面,就说明这个程序依赖于CRT 9.0,而且是调试版的,CPU架构是32位的CPU。对于将manifest文件嵌入到资源文件的程序我们也有办法看到manifest的信息。

1.         一种是使用mt.exe(Visual Studio自带的manifest处理程序):

mt -inputresource:test.exe;#1 /out:test.manifest

2.         另外一种是使用dumpbin程序将整个exe的内容打印到一个文件,然后用文本编辑器打开,搜索Assem字符串样式就能找到manifest信息:

解决方案

知道了程序依赖于具体哪一个dll以后,你可以将所依赖的dll拷贝到程序的安装文件夹里面,以CRT库绑定失败为例,介绍解决步骤:

1.         从上例中我们知道程序依赖的Microsoft.VC90.DebugCRT库,版本号是9.0.21022.8,需要32位机器版本的CRT。这个依赖项一般是因为你的程序是调试版,所以Visual Studio在编译的时候,将调试版的CRT加入程序的依赖项。

2.         从Visual Studio的安装文件夹里面将D:"Program Files"Microsoft Visual Studio 9.0"VC"redist"Debug_NonRedist"x86中的Microsoft.VC90.DebugCRT整个文件夹拷贝到应用程序所在的文件夹里面,注意:

a)         如果你的程序依赖的是32位的CRT,则要拷贝x86文件夹里面的Microsoft.VC90.DebugCRT文件夹,如果是先x64程序,则要拷贝x64文件夹里面。

b)         你需要确定Microsoft.VC90.DebugCRT文件夹里面的Microsoft.VC90.DebugCRT.manifest文件里面保存的版本信息而你程序依赖的版本信息匹配,Microsoft.VC90.DebugCRT.manifest里面的版本信息大版本号一定要一致,小版本号一定要等于或者大于你程序依赖的CRT的小版本号。比如上例中,我们的程序是依赖于CRT 9.0.21022.8,而我们的Microsoft.VC90.DebugCRT.manifest的版本是9.0.30729.1,这样是可以的;而8.0.30729.1就会有问题。如果大版本号一样,小版本号不一致的话,一个比较简单的方案就是修改程序的manifest文件,使其互相匹配就可以了。

3.         如果你的程序不是依赖调试版本的CRT,而是release版本的CRT,直接去微软的官方网站下载一个crt redist包安装上就可以了。

VC编写的程序不能在其他机器上运行的解决方案相关推荐

  1. VC编写的程序不能在其他机器上运行的解决方案(续)

    我在前面的文章里面提到由于side-by-side问题导致的VC编写的程序不能正常启动的问题的解决方案,这种方法是针对于单个可执行文件的解决方案,但是有的时候你可能会碰到另外一种情况-也是由于side ...

  2. 32位系统上开发的Access为数据库的程序在64位机器上运行出错的解决办法

    64位平台下解决方法为在VS2010开发环境下进行以下操作:生成->配置管理器->平台->点击Any Cpu选项卡->新建->新建平台->X86

  3. VC++编写电子邮件程序 第二篇 也是用simple mapi

    VC++编写电子邮件程序 一.概述 ---- 本文主要讲述如何使用Visual C++用MAPI编写E-mail程序.MAPI是包含在Windows之中的, 因此不需要安装其他额外的部件.MAPI有以 ...

  4. MFC编译出来的程序不能在其他机器上用

    VC编译出来的程序不能在其他机器上用?Win32程序需要将运行时库设置成静态 具体操作:项目 -> 属性 -> C/C++ -> 代码生成 -> 运行时库 -> 多线程( ...

  5. VS2010生成的文件在别的机器上运行提示“丢失MSVCR100D.dll”

    用vs2010编写的程序经常会发生的一个问题.在自己的机器上运行的好好的,但是在别的机器上就会发生没有找到MSVCR100D.dll.这是 个很头疼的问题.对于一些代码量几百行的小程序,我不可能要求其 ...

  6. php和mysql不在一台机器上_MySQL_在同一台机器上运行多个 MySQL 服务,**************************************** - phpStudy...

    在同一台机器上运行多个 MySQL 服务 ********************************************************** 第一部分, 在一台服务器构建多mysql ...

  7. 在同一台机运行多个mysql 服务 多个主/从在同一主机_在同一台机器上运行多个 MySQL 服务...

    在同一台机器上运行多个 MySQL 服务 ********************************************************** 第一部分, 在一台服务器构建多mysql ...

  8. 32位程序在64位系统上运行

    32位程序在64位系统上运行 32位系统下的MFC文件,怎么在64位的系统上面运行? 先将32位的应用程序转换为64位的应用程序. 从32位应用程序到64位应用程序 编译:starlight 这篇文章 ...

  9. 都有哪些应用程序可以在M1 Mac上运行?

    如果您有幸使用新的M1 Mac,或者考虑购买一台Mac,您会想知道您需要使用的应用程序是否可以在其中运行. 苹果公司拥有Rosetta 2-一种用于翻译用于英特尔处理器的代码的工具,以便M1芯片可以理 ...

最新文章

  1. ubuntu安装thrift
  2. HDU-1042 N! 大数乘法 (C语言)
  3. Java - HtmlEmail 邮件发送
  4. java大佬是如何快速配置IntelliJ IDEA的Tomcat及安装配置Tomcat及java开发环境
  5. 你单身,其实是个科学问题……
  6. Discuz模板 轻社区Qing_freefresh 完整版
  7. Python之网络编程(基于tcp实现远程执行命令)
  8. pyqt5使用label显示图片
  9. Git教程——merge 分支冲突
  10. 惊呆了!JDK1.8竟然打破了我对接口的一切认知...
  11. 用glew,glfw,FreeImage实现opengl学习笔记6坐标变换
  12. 【转】echarts x轴标签文字过多导致显示不全
  13. 面试必备:消息队列原理和选型(荣耀典藏版)
  14. 不用格式化,5条命令,让Macbook支持ntfs硬盘读写
  15. @程序员:连小学生都开始学编程了,你们怕了吗?
  16. cocos creator pc web端 全屏
  17. CentOS6安装rpm时报错“Cannot find a valid baseurl for repo: centos-sclo-rh“的解决办法
  18. PayPal 如何付款
  19. 昆山市地方税务局异地复制及备份系统询价采购招标公告
  20. 北大CSAPP期末题

热门文章

  1. c语言数据库线程池,C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0...
  2. python中json模块博客园_python的json模块
  3. python数据库哪个好_终于明了python用什么数据库好
  4. numa对MySQL多实例性能影响
  5. 2018-01-17 Antlr4实现简单语言之整数比较表达式
  6. day3 and homework
  7. Asp.net HttpClient Proxy(Fiddler)
  8. HDU 3068 最长回文
  9. asp.net中退出登陆的相关问题(解决后退或直接粘贴地址进入网页的问题)
  10. 一个完整的canvas画图