现在的位置: 首页 > 综合 > 正文

VC-”应用程序正常初始化失败”-0xc0150002

2018年05月04日 ⁄ 综合 ⁄ 共 6185字 ⁄ 字号 评论关闭

最近几天被这个问题困惑了许久。 不禁感叹微软的东东真是越做越烂了,也终于明白了时隔12年大家仍然死守VC6的原因。。 

  用VC2005/VC2008编译的程序,编译时没有任何错误,但是运行时就是提示“应用程序正常初始化失败”!! 查找了各方面资料,做了各种尝试,网上说什么的都有:有让安装vc2005 sp1补丁的;有让安装vcredist_x86.exe的; 有让把CRT库的dll直接拷贝到程序目录的; 有让清理注册表的;有让装.NetFramework新版本的;有让查manifest的; 

  结果我尝试了半天,几乎都是浪费时间。上面最后一条说的还算正确,只是作者把事情描述得太繁琐了。。现在把处理的方法说一下,省得大家再走弯路: 

  1. VC2003、VC2005、VC2008及其后续版本,对底层最基本的CRT、MFC、ATL库都进行了重构,为了避免不同版本的库引起冲突,重构后的库文件一般放在 C://windows/WinSxS 文件夹中,并用特定的文件夹/文件名称进行标识; 

  2. 与VC6不同, VC2003、VC2005、VC2008及其后续版本,引入了manifest清单的概念,即应用程序编译后会同时生成对应的.manifest文件,并将该.manifest文件作为资源编译到dll或者exe中去。.manifest文件实际上是一个XML格式的文本文件,里面记录了dll或exe中要引用的CRT、MFC、ATL库的版本和名称。VC6编译的应用程序对CRT、MFC、ATL的dll都是直接调用,而VC2003、VC2005、VC2008编译的程序都是先查询编译到资源中的manifest中的记录,然后按照记录提供的版本和名称去搜寻对应的CRT、MFC、ATL库以及随库发布的.manifest文件,搜寻的路径包括当前目录、C://windows/WinSxS
等等,如果没有找到对应的库文件,则提示“应用程序正常初始化失败”; 

  3.因此解决这个问题的办法就是:(a)用文本编辑器打开exe或dll对应的.manifest文件,查看它引用的CRT、MFC、ATL库的版本;或者,用UltraEdit直接打开exe或者dll,从资源区中找到编译进去的.manifest信息,找到它引用的CRT、MFC、ATL库的版本;或者,运行程序,当程序弹出“应用程序正常初始化失败”对话框时,在桌面上右键点击“我的电脑”-“管理”-“事件查看器”-“系统”,双击查看其中的记录,可以看到出错的原因是因为缺少了某某版本的CRT、MFC、ATL库,记录下这个版本信息;(b)记录到的库的版本信息一般类似于“Microsoft.VC90.DebugCRT”,之后到C://windows/WinSxS
或者VC200X的安装文件夹中搜索包含这个字符串的文件夹和文件,将搜索到的dll和.manifest文件都拷贝到应用程序所在的文件夹中,其中,.manifest文件必须重命名为“Microsoft.VC90.DebugCRT.manifest”(这里以Microsoft.VC90.DebugCRT为例),这样应用程序就可以正常运行了;(c)注意:库的.manifest文件和dll要一同拷贝到应用程序根目录去,因为应用程序会将编译到内部的manifest信息与外部的.manifest文件进行对比,之后才会对库的dll进行调用。如果只拷贝库的dll文件是没有用的; 

  4.如果本机编译和运行程序都ok,但是将编译好的程序拿到其它机器上确无法运行,则多半也是这个原因。另外,如果提示"应用程序配置不正确",大多也是因为上面所说的CRT、MFC、ATL库版本与应用程序不匹配导致的,可以如法炮制进行解决; 

 

*****************************************

注意

主要的原因是没有vs开发环境的运行环境CRT、MFC、ATL库版本的问题

安装相应vs版本运行库即可

方法二:

        写了一个VC6下的MFC程序,结果拷贝到另一台机子上出现了应用程序正常初始化(0xc0150002)失败的问题。然后打开事件查看器,

找到了如下信息:

找不到附属汇编 Microsoft.VC80.DebugCRT,上一个错误是 参照的汇编没有安装在系统上。

Resolve Partial Assembly 为 Microsoft.VC80.DebugCRT 失败。 参考错误消息: 参照的汇编没有安装在系统上。
Generate Activation Context 为 C:\Documents and Settings\jerry\桌面\ProConfigure\Debug\MXML1.dll 失败。 参考错误消息: 操作成功完成。

        可以判断是dll加载的时候出了点问题了,看了下它的manifest文件,其依赖库是Microsoft.VC80.DebugCRT ,这样问题就很明显了,
这个dll是在VS2005下编译的,而别人的机子上没有这个环境,我们所编译生成的应用程序由于缺少必需的Debug版本的VC运行库而发生错误。

        解决方法:到第一台机子上的vs2005的安装目录下,搜索名字中包含串Microsoft.VC80.DebugCRT的文件,共有3个dll文件msvcm80d.dllmsvcp80d.dllmsvcr80d.dll和一个manifest文件(Microsoft.VC80.DebugCRT.manifest),拷贝到另一台机
子上的工程可执行文件目录下,问题就解决了。


方法其他:

vs2005做的c++,在本机都能运行,然后到虚拟机(.net framework2.0已经安装,还安装了vcredist)

控制台程序--正常;
MFC应用程序(使用静态库)--正常;

MFC应用程序(使用共享DLL)--报错;
窗体应用程序--报错;

错误星信息一样:“由于应用程序不正确,程序不能启动.重新安装应用程序可能会解决这个问题.”

如果是c#做的窗体应用程序的话,在这个虚拟机里是能运行的。
哪位大哥能讲讲是为什么啊?


解答:

首先以及再次感谢Avoid兄,乃素好人呐~ ^-^
终于解决问题了,把经验贴出来,方便以后有人遇到此类问题时解决

Avoid兄给出的链接里的四种方法的可行性说明以及详细运行过程:
关于“由于应用程序不正确,应用程序不能启动......”
方法一基本可行,方法二和方法三也可行,方法四估计不可行。
方法一:
在X:\Microsoft Visual Studio 8\VC\redi
st\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT 下找到了下列文件:
msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest //其实就是所有文件-_-!
把这几个文件拷贝到目标机器上,与运行程序同一文件夹,就可以运行那个程序了。

之所以说基本可行是因为那文章中所提到的“或者拷贝到SYSTEM32文件夹下”是不可行的,在这里我去掉了。
还有就是,未必一定得是Microsoft.VC80.DebugCRT,如果你建立的是“windows窗体应用程序”项目就用Microsoft.VC80.DebugCRT,如果你建立的是“MFC应用程序”项目那就用Microsoft.VC80.DebugMFC

其实这个方法以前看到过,不过我搞错文件夹了,一直拖到今天才弄清楚,各位注意了在和Debug_NonRedist同级的文件夹里也有个X86,不是它,别进错了!

方法二和方法三其实是联系在一起的:
方法二:
工程-》属性-》配置属性-》代码生成-》运行时库,将/MD或/MDd 改为 /MT或/MTd,这样就实现了对VC运行时库的静态链接,在运行时就不再需要VC的dll了。注:MDd和MTd是DEBUG版本的,不带小d的是RELEASE版本.

方法三:
工程-》属性-》配置属性-》常规-》MFC的使用,选择"在静态库中使用mfc"
这样生成的exe文件应该就可以在其他机器上跑了。
而这两个方法就是我在主贴里提到的“MFC应用程序(使用静态库)--正常; ”,也就是当你在建立“MFC应用程序”项目时在向导的第二步中选择了“在静态库中使用MFC”,得到的就是方法二和方法三联合起来的效果。

方法四:
在主贴里已经说明了,我虚拟机里是装了vcredist的。
vcredist是微软官方出的一个东西,关于它的说明“Microsoft Visual C++ 2005 SP1 Redistributable Package (x86) 安装在未安装 Visual C++ 2005 的计算机上运行使用 Visual C++ 开发的应用程序所需的 Visual C++ 库的运行时组件。”
但是编的程序仍然无法运行,后来我卸载了它,今天为了验证这四种方法,又重装时,竟然无法安装了!!!无论是最初的版本还是这个月15号出的SP1版!!!微软出它来到底是干什么的...-_-! 希望诸位看官能给个答案...

呵呵~终于搞完了,下面是第一次来运用CSDN的“给分”功能了,希望别再像上次一样失败...
话说“结贴”了的话今后是不是无法再回复了?
这样很不好哎,如果这次收获了个相对不错的答案给了分,那今后不就得不到更好的答案了么?也或者下次面对更好的答案却无法给回答人分数了?



在VC++2008的项目中,如何显示地指定要使用的C++库的版本? 

开发环境:VS2008 SP1 + Win2003 SP2 
        因为我的VS2008安装了SP1补丁,所以有了9.0.30729.1的MFC库文件(MFC90.DLL MSVCR90.DLL)。 


新建了一个MFC应用程序,编译为RELEASE版本,叫做“test1.exe”,可以从程序中的清单文件(manifest)看到以下内容: 

XML code
... <dependency>

<dependentAssembly>

<assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'/>

</dependentAssembly>

</dependency>

<dependency>

<dependentAssembly>

<assemblyIdentity type='win32' name='Microsoft.VC90.MFC' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'/>

</dependentAssembly>

</dependency> ...

说明本程序需要引用版本号为9.0.21022.8的MFC库和运行时库。 

问题一:为什么程序在运行的时候,载入的不是9.0.21022.8版本的却是9.0.30729.1版本的运行库?这是在哪里进行设置的?如何改变这个版本号? 

问题二:(虽然貌似已经解决,但是我想知道的更深一点) 
布署的时候,把X:\VS安装目录\VC\redist下对应的运行库和.manifest文件(都是9.0.30729.1版本的)复制到与test1.exe同一目录下。在一台完全干净的新系统中,会出现“应用程序配置不正确,应用程序未能启动”的错误。 

后来,经过不断的试验,发现应用程序中的MANIFEST文件指定的是9.0.21022.8版本的运行库,然后我使用9.0.21022.8版本的Microsoft.VC90.CRT.manifest文件替换9.0.30729.1版本的Microsoft.VC90.CRT.manifest,配合上30729版本的MFC90.DLL,程序就可以正常运行了。 

简单一点,就是,对于一个使用了新版本DLL功能的应用程序,有以下情况: 
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 不可以运行 
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 旧版本的运行库DLL --> 不可以运行 
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行 

注:运行库MANIFEST文件是指Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest,运行库DLL是指MSVCR90.DLL MFC90.DLL 

程序的清单文件不要内嵌,而使用外置的MANIFEST文件,然后手工把生成的text1.exe.manifest中的version='9.0.21022.8'改成新版本号version='9.0.30729.1' ,就可以达到以下目标了: 
应用程序 外置的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行! 
(内嵌清单也是资源,当然可以修改,但是不建议这么做,而且也没必要这么做。)

终于终于,在微软网站找到了关于这个问题的描述。 

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361682 

这的确是个BUG,具体什么时候会修复就不知道了。。。。。。。。 

所以,内嵌清单中的版本号只能为旧版本号,因此目前只能用,旧版本的运行库MANIFEST文件 + 新版本的运行库DLL ,才可以运行独立发布的程序了。。。

在VS2008中,“项目”-->“属性”-->“配置属性”-->“清单工具”-->“输入和输出”-->“嵌入清单”-->否。

这样程序编译后,假设是mytest.exe,将会产生一个mytest.exe.manifest,发布软件时最好附带上这个manifest文件,用记事本打开,可以看到对应MFC/CRT.manifest的版本。

在VS2008中,“项目”-->“属性”-->“配置属性”-->“清单工具”-->“输入和输出”-->“嵌入清单”-->是。mytest.exe将包含mytest.exe.manifest,不额外产生mytest.exe.manifest。

“配置属性”其它设置:(1)常规-->MFC的使用:在共享DLL中使用MFC;(2)C/C++  -->检查64位可一致性问题:否;(3)C/C++  -->代码生成-->运行时库:多线程调试DLL(/MDd);(4)链接器-->清单文件-->生成清单:是

详解Manifest(清单)文件使用

http://impd.tencent.com/?p=37

抱歉!评论已关闭.