• VS2008环境下开发的某些程序在其他机器运行提示“由于应用程序配置不正确,应用程序未能启动”的问题(IIS)


    比较全的有关vs2008部署问题集(1):

    http://blog.csdn.net/buhuizheyangba/article/details/7220598

    比较全的有关vs2008部署问题集(2):

    http://blog.csdn.net/fengbingchun/article/details/6449241

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    原文地址:http://www.360doc.com/content/11/0125/17/61151_88963969.shtml

    VC9编译的程序在没有装过VC9(确切的说是.Net Framework3.5)的机器上运行时,如果提示“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。”这个错误,那么就说明该程序动态链接了VC9的运行时库,(如果还用到了MFC,那么可能动态链接了VC9的MFC库,同理还有ATL库),以及缺少对应的 manifest文件,程序在目标机器上没有找到这些库和配置文件,因此导致了这个错误。出现这种情况的VC9编译器可能存在3个版本,接下来分别阐明:

    1、没有打过任何补丁的VS2008

    该版本对应的CRT/MFC/ATL库的版本号为9.0.21022.8,这个版本号在后面会用到。这个版本的程序部署比较简单,直接把VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

    2、打过SP1补丁的VS2008

    打过该补丁后,系统中存在着两个版本的CRT/MFC/ATL库,版本号分别为9.0.21022.8和9.0.30729.1,这导致了 manifest文件中记录的版本号和实际库的版本号不一致(程序要求它们的版本号一致才能运行)。这个版本的程序部署需要两个步骤,首先要使 manifest文件中依赖项的版本号与实际库的版本号一致,均为9.0.30729.1,方法是在工程设置中增加一个宏定义 _BIND_TO_CURRENT_VCLIBS_VERSION,该宏定义于C:\Program Files\Microsoft Visual Studio 9.0\VC\include\crtassem.h文件中,然后重新编译程序。接下来还是将VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,然后修改manifest文件中依赖项的版本号为 9.0.21022.8,这样使得程序误以为该目录下库的版本号为9.0.21022.8(实际上是9.0.30729.1版本),这样程序到任何机器上都能够正常运行了。

    3、打过SP1补丁与SP1 ATL 安全更新 (KB973675)的VS2008

    这是最新的更新。在SP1补丁之后,微软又于近日发布了一个用于智能设备的 Microsoft Visual Studio 2008 Service Pack 1 ATL 安全更新 (KB973675),该补丁又将CRT/MFC/ATL库的版本号升级,为9.0.30729.4148,这次升级比较好,manifest文件与库的版本号一致了,不像 SP1一样升级的不彻底。这样只需要在工程设置中增加一个宏定义_BIND_TO_CURRENT_VCLIBS_VERSION,接下来重新编译程序,然后直接把VC安装目录下的redist目录中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

    顺便提一下,如果不想在发布程序时带上这些库和manifest文件(如果没有必要的话),那么可以采用静态编译CRT和MFC,然后把manifest文件添加到资源中,这样编译出的程序只要一个exe就可以在任何机器上直接运行了。

    参考文章:

    1、“应用程序配置不正确,程序无法启动”的解决方法资料收集:http://hi.baidu.com/fairysky/blog/item/e7a8366dbaa735f3431694c8.html

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

    VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题 - tangxingqt - doomgnu的博客

    一般情况下,这个问题都是由于程序不能找到所需要的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信息:

    VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题 - tangxingqt - doomgnu的博客 

    解决方案

    知道了程序依赖于具体哪一个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包安装上就可以了。

    ==============<>

    如果你编译了一个VC2008的默认的CRT/MFC的应用程序,如果目标部署电脑上没有安装相应的VC2008的动态库,当运行你的程序的时个,会出现如下错误信息.

    这是因为程序使用了基于VC2008的CRT/MFC的动态库版本.

    解决这个问题,有三种方法:

    1.使用静态链接库编译(缺点,生成的exe的程序过于庞大)

    2.使用vcredist_x86.exe / vcredist_x64.exe 将VC2008的发行版的DLL安装在你的系统上.(缺点,只能支持发行版,调试版程序不能支持)

    3.将你的程序依赖的CRT/MFC的动态库与你的程序一起发布(放在与你的发布程序同一目录中)

    第一种和第二种就不详细讲如何实现了,只要讲第三种方法如何实现.优其是程序的开发是使用了VC2008 SP1的版本开发的程序.

    在你的VC2008的安装目录下有两个目录,

    • C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.CRT
    • C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.MFC

    只要将这两个目录下的文件一同拷贝到发布程序的同一目录下:

    • Microsoft.VC90.CRT.manifest
    • msvcr90.dll
    • msvcp90.dll
    • msvcm90.dll
    • Microsoft.VC90.MFC.manifest
    • mfc90.dll
    • mfc90u.dll
    • mfcm90.dll
    • mfcm90u.dll

    这些是这个程序依赖的发行版动态库,同理,如果是调试版的发布程序,也一样把相应的调试动态库拷贝到相应目录.

    程序如你意运行起来了!

    但是,如果你安装的是VC2008 SP1的版本的时候,问题就来了,你的程序也一样运行不起来了!

    原因就是安装了VC2008 SP1的时候,它把"VC/redist"用新的版本文件代替了,问题不大,但是,这个程序的版本是依赖于新的manifest的文件的,当你编译VC2008-SP1的程序的时候,它同时把RTM-version写入程序的manifest文件中,这个是旧的RTM-version,不与新版本的VC2008-SP1的"CRT/MFC"manifest版本一致,因此程序运行的时候是拒绝导入这些新的VC2008-SP1的CRT/MFC的运态库!

    解决方法有两种.

    方法一:

    最简单的,修改Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest文件,将新的版本号改为旧的版本号,如果是依赖其它的Microsoft.VC90.*.manifest的文件,也同样是如此修改!

    如果是装了VC2008-SP1后,它的版本号是“9.0.30729.8″

    未装VC2008-SP1前的版本号为"9.0.21022.8"

    过程如下:

    将所依的动态库的及它们的 manifest 文件拷贝到发布应用程序的同一目录下,并修改Microsoft.VC90.*.manifest文件,将

    version="9.0.30729.1"
    
    
    修改为
    version="9.0.21022.8"
    恭喜你,你的程序运行起来了!

    方法二
    修改你的程序的所依赖的manifest,这样程序会依整于新的manifest.
    过程如下:
    stdafx.h 这个文件中,增加如下宏定义:

    #define _BIND_TO_CURRENT_VCLIBS_VERSION 1
    程序编译后就会依赖于新的manifest,版本号为
    "9.0.30729.1"

    无须再修改manifest文件中的version版本号了.
    将所依的动态库的及它们的 manifest 文件拷贝到发布应用程序的同一目录下
    恭喜你,程序又运行起来了!

    注意:如果你是想要新的MFC-feature-pack的功能,用这种方法是最好的.

    注意一点,非常重要,如果已经安装了vcredist_*.exe程序包,注意的是Dll会自动把引用调到系统目录下的WinSxS目录下的,即不再引用同一目录下的动态库!
    如果是编译时使用了(/clr)这个编译选项去支持.net开发,你必须要安装.net framework redistributable包!

    不过,在2010,编译的程序会不再需要manifest文件!
    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    总结如下:

    使用vs2008/vs2008开发的程序有2种部署方法:共享并行程序集和私有程序集部署方法

    所谓的共享并行程序集部署方法是指程序依赖的CRT、MFC、ATL的DLL和manifest文件位于目标机器上的c:/windows/winsxs目录中,发布程序的时候只需要将程序拷贝到目标机器上就可以了;私有程序集部署方法指的是发布程序程序的时候,将所依赖的crt、mfc、atl的dll放在程序的当前目录下

    对于release版程序

    比较的简单的方法是采用共享程序集的方式来部署,安装vcredist.exe (Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)

    也可以采用下面debug程序的私有程序集的部署方法

    对于debug版本程序

    ◆ 若目标机器安装了VS开发环境(vs2005 sp1/vs2008 sp1),则在机器上同时也安装了共享并行程序集,包含各个版本的dll(8.0、9.0版本,位于C:/Windows/Winsxs目录下),则不需做任何的部署,直接将需要发布的程序拷贝到目标机器上就可以了,这和release版程序的发布方式是一样的

    ◆ 在没有安装VS开发环境(安装了vs2005 sp1/vs2008 sp1)的机器上,只能采用私有程序集的方式来部署(因为vcredist.exe只安装了release版的CRT、MFC、ATL的DLL和manifest文件,没有对应的debug版本)

    已知的2种方法:(针对vs2008 sp1,安装了sp1之后,在系统上会存在两个版本的CRT、MFC、ATL的DLL:9.0.21022.8和9.0.30729.1)

    1、使当前程序的manifest文件中的依赖项的版本号与vc安装目录下的redist目录下的dll的版本一致,均为9.0.30729.1

    方法:

    a、在编译项目时定义一个符号_BIND_TO_CURRENT_VCLIBS_VERSION,该符号定义于C:/Program Files/Microsoft Visual Studio 9.0/VC/include/crtassem.h 文件中(假设VC安装在c盘),这样使得编译后的程序的manifest依赖于CRT 9.0.30729.1版本(同样的,对于MFC也应该定义一个类似的符号,大家可以自己在VC的include目录下搜索“9.0.30729.1”或“9.0.21022.8”,就可以找到对应的定义该符号的头文件)

    b、通过外部工具修改生成的exe或dll中manifest文件(好像windows sdk中的mt.exe可以做到,不过关于这个工具的资料十分的少)

    2、将VC安装目录下的redist目录下(C:/Program Files/Microsoft Visual Studio 9.0/VC/redist)的Microsoft.VC90.CRT拷贝到要发布的程序的当前目录下,修改Microsoft.VC90.CRT目录中的Microsoft.VC90.CRT.manifest文件中的版本号,改成9.0.21022.8,这样使得程序误以为该目录下的vc的dll版本是9.0.21022.8(实质上仍然是9.0.30729.1版本)


  • 相关阅读:
    iOS基础
    iOS基础
    iOS基础
    iOS基础
    iOS基础
    iOS基础
    iOS基础
    简单DP + 高精
    高精度计算
    树 (tree)
  • 原文地址:https://www.cnblogs.com/wainiwann/p/2722222.html
Copyright © 2020-2023  润新知