14001错误:由于应用程序配置不正确,应用程序未能启动:OD调试解决办法

5bce955cf12af3417f055dadc0212920

“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。”


此md5为QQ浏览器带有效数字签名的文件,说明是正常文件,但直接运行时,显示配置不正确。用OD直接无法加载。

明明是好的PE文件,为什么OD无法加载?直接用WinDBG加载,会显示Win32 error On14001错误。

以前用VC6和VS2003的话, 如果缺少库文件,是会提示缺少“**.dll”,但是用VS2005却没有这样的提示。所以,上面提示应该是缺少dll。

查看导入表,确实需要一个dll,在网上找了一个一样的,放到同目录下,还是显示上面错误。



很是奇怪,还有需要导入的dll文件?分析资源时,看到该文件里有mainifest,把mainifest用ResHacker删除后,再用OD加载,发现可以正常加载了。这是为什么?

专门去查了下资料,可百度:程序集清单(Assembly Manifest)的应用。发现mainifest中有个assemblyIdentity字段,字段中有个version,这个version用来指定版本路径的,简单点说就是这个version是"9.3.6494.400",那么在这个PE文件下就必须要有个文件夹叫"9.3.6494.400",在这个文件夹下里面存着相关dll文件。


为了证实说法,去QQ浏览器官方下载并安装了,将安装目录下的9.3.6xxx.xxx文件夹复制到了这个PE文件同目录下,双击运行会报上面的错误,将文件夹名改为"9.3.6494.400"再双击后发现,PE可以直接运行起来了。








以下为相关查找的资料:

百度:dll文件加载运行加载的14001错误,由于应用程序配置不正确,应用程序未能启动

http://blog.csdn.net/huapeng_guo/article/details/7774876


最近在处理项目问题的的时候发现了这么一个问题,就是我们的程序在调用第三方提供的dll文件的时候在一台机器上面会报14001的错误,但是在另一台机器上面不会。两台机器上面的操作系统是相同的。针对这个问题和这个错误码,查找了很多的相关资料。

vc错误查找的给予的对于14001的错误的解释:由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。 


下面是搜集的一些网络资料针对这个问题的说明和解决方法个人感觉还是很有参考意义的:


资料


在VS2005下用C++写的程序,在一台未安装VS2005的系统上,
用命令行方式运行,提示:
“系统无法执行指定的程序”
直接双击运行,提示:
“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”


以前用VC6和VS2003的话, 如果缺少库文件,是会提示缺少“**.dll”,但是用VS2005却没有这样的提示。


自己实验了一下,感觉以下几种解决办法是可行的:
方法一:
在类似C:\Program Files\Microsoft Visual Studio 8\VC\redi
st\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT 下找到了下列文件:


msvcm80d.dll
msvcp80d.dll
msvcr80d.dll
Microsoft.VC80.DebugCRT.manifest


把这几个文件拷贝到目标机器上,与运行程序同一文件夹或放到system32下,就可以正确运行了。


其他release版、MFC程序什么的都是拷redist下相应文件夹下的文件就可以了,文件夹后都有标识!


方法二:
修改编译选项,将/MD或/MDd 改为 /MT或/MTd,这样就实现了对VC运行时库的静态链接,在运行时就不再需要VC的dll了。


方法三:


工程-》属性-》配置属性-》常规-》MFC的使用,选择“在静态库中使用mfc”
这样生成的exe文件应该就可以在其他机器上跑了。


方法四:


你的vc8安装盘上找到再分发包vcredist_xxx.exe和你的程序捆绑安装。




如果安装Microsoft Visual C++ 2005 出现如下错误↓:


事件查看器显示:产品: Microsoft Visual C++ 2005 Redistributable -- Error 1935.安装程序集“Microsoft.VC80.ATL,type="win32",version="8.0.50727.4053",publicKeyToken="1fc8b3b9a1e18e3b",processorArchitecture="x86"”过程中发生错误。请参阅帮助和支持获取详细信息。HRESULT: 0x80070422。程序集接口: IAssemblyCacheItem,功能: Commit,组件: {97F81AF1-0E47-DC99-A01F-C8B3B9A1E18E}




解决方法:启动 Windows Modules Installer 服务,再安装。OK,解决。




http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/66bc8cab-c134-49a8-85e5-37ca9efbdeb4/


个人问题解决过程:


1.考虑的是两个方面:

一个是程序调用的dll是否提供了所要的方法;

一个是dll所依赖的dll是否完整。

这两方面都是通过depends工具来查看


2.我的问题是我用的是别人提供的dll文件自己不可以去更改dll文件的生成方式,因此所做的工作就是设法去导入dll所依赖的dll文件。

(1)配置系统环境变量的path路径使dll做可能依赖的系统dll文件能够找到依赖的dll。

(2)推测第三方所提供的dll开发时候应该用的是vs2005或者vs2008在或者就是vs2010,然后所提供的dll文件或许就是动态加载的dll,所以安装了vcredist_x86的vs2005,vs2008以及vs2010版本的,这个地方的操作对于我解决问题起了作用,但是具体是哪一个这个没有去确定

(3)为了使自己程序运行的环境没有必要都去安装vcredist_x86所以找到vcredist_x86安装之后对应的dll文件和调用的第三方的dll放在同一个目录下面,也可以放在C:\WINDOWS\system32但是path路径中的配置一定要有,一般来说都是会有的。

通过上面的三个方面个人的问题是解决了,当然具体到个人的项目里面还有很多的方面要考虑,但就这个dll加载的14001错误,上面的解决方法还是ok的。网上的相关资料还是很多的,希望个人整理的这些对你有小小的帮助。针对vcredist_x86的dll文件以及vs2005,vs2008 和 vs 2010对应的exe安装文件可以搜一下,我也把我搜到的上传一下,共享。















程序集清单(Assembly Manifest)的应用:

http://blog.csdn.net/xinfeiyang0605021/article/details/46686763

最近在工作中碰到一个软件版本发布的问题:在本地开发了一个服务端程序,在自己的计算机上能毫无问题地运行,但是当发布出去在一个纯净的win7环境下运行无法正常加载动态库,报加载库的错误为“14001”,于是在网上查找相关资料,发现相关解决问题的方式,做一下总结。 原来这一切都是Windows 的Assembly Manifest(程序清单文件)有关。这个文件的作用就是为了解决以前windows上的“Dll 地狱” 问题才产生的新的DLL管理解决方案。大家知道,Dll是动态加载共享库,同一个Dll可能被多个程序所使用,而所谓“Dll 地狱”就是当不通程序依赖的Dll相同,但版本不同时,由于系统不能分辨到底哪个是哪个,所以加载错了Dll版本,然后就挂了。于是win平台搞了一个“程序集清单”的概念,每个运行的程序都要有一个清单,这个清单保存在和自己应用程序同名的.manifest文件中,里面列出其所需要的所有依赖,这儿所列出的依赖可不是简单地靠文件明来区分的,而是根据一种叫做“强文件名”的东西区分的,那么什么是强文件名呢?我们来看一下这个.manifest文件(客户端-使用库的可执行文件)便知道了:

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

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

<dependency>

<dependentAssembly><assemblyIdentitytype='win32'name='Microsoft.VC80.CRT'version='8.0.50608.0'processorArchitecture='x86'publicKeyToken='1fc8b3b9a1e18e3b'/>

</dependentAssembly>

</dependency>

</assembly>

通过上面大家发现原来这是一个XML格式的文件,其中<dependency>这一部分指明了其依赖于一个名字叫做Microsoft.VC80.CRT的库。但是我们发现,<assemblyIdentity>属性里面还有其它的东东,分别是type系统类型,version版本号,processorArchitecture平台环境,publicKeyToken公匙(一般用来标示一个公司),只需要把他们加在一起便组成了“强文件名”,有了这种“强文件名”,我们就可以根据组合文件名区分不同的版本、不同的平台……总之,有了这种强文件名,系统中可以有多个不同版本的相同的库共存而不会发生冲突。 那么现在,我们就来具体了解一下这一套机制。 首先是强弱文件名的问题。正如上面提到的那样,为了区分不同版本或不同厂商生成的相同的程序集,必须用一个Assembly Manifest程序清单来列出我这个程序集的强文件名--慢着,到这里你可能会问:刚才不是说Assembly Manifest程序清单是列出其所依赖的程序集的强文件名呢,怎么这里变成了当前文件的强文件明了呢?其实,Assembly Manifest程序清单有两部分功能,上面这个实例之所以标注了其所依赖的文件的强文件名是因为其是客户端的Assembly Manifest,在服务端有另外一个Manifest 来标注。

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

<assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestVersion="1.0">

<noInheritable>

</noInheritable><assemblyIdentitytype="win32"name="Microsoft.VC80.CRT"version="8.0.50727.42"processorArchitecture="x86"publicKeyToken="1fc8b3b9a1e18e3b">

</assemblyIdentity>

<filename="msvcr80.dll"hash="2a0d797a8c5eac76e54e98db9682e0938c614b45"hashalg="SHA1">

<asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">

<dsig:Transforms>

<dsig:TransformAlgorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform>

</dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</dsig:DigestMethod>

<dsig:DigestValue>phRUExlAeZ8BwmlD8VlO5udAnRE=</dsig:DigestValue>

</asmv2:hash></file><filename="msvcp80.dll"hash="cc4ca55fb6aa6b7bb8577ab4b649ab77e42f8f91"hashalg="SHA1">

<asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">

<dsig:Transforms>

<dsig:TransformAlgorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform>

</dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>7AY1JqoUvK3u/6bYWbOagGgAFbc=</dsig:DigestValue></asmv2:hash></file><filename="msvcm80.dll"hash="55e8e87bbde00d1d96cc119ccd94e0c02c9a2768"hashalg="SHA1">

<asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">

<dsig:Transforms><dsig:TransformAlgorithm="urn:schemas-microsoft-com:HashTransforms.Identity">

</dsig:Transform>

</dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">

</dsig:DigestMethod><dsig:DigestValue>hWq8zazTsMeKVxWFBa6bnv4hEOw=</dsig:DigestValue>

</asmv2:hash>

</file>

</assembly>

这个便是从WINDOWS/WinSxS/Manifests目录下取出来的一个manifest文件,在这个文件夹下有许多这种XML格式的manifest文件,其是服务端的程序清单,此外,还有一个文件的文件名也与程序集同名,但是后缀名为 .cat,这是一个已签名的安全编目文件,其包含了程序集中文件的hash值,正是因为它已签名,所以可以防止被篡改。WinSxs是windows XP以上版本提供的非托管并行缓存(side-by-side catche)里面安装了各种版本的经过强文件名签名的系统库,而上面这个文件<assemblyIdentity>正是标注了系统中Microsoft.VC80.CRT的一个版本的强文件名签名,如果其和客户端的.manifest 清单里面<dependentAssembly>所列出的依赖项对上的话,就会被加载。刚才说的side-by-side 是指各种不同的版本并行运行。上面这个服务端manifest文件中<file>标签具体指明了当前强文件名签名的到底是哪一个文件,其中还有这个文件的Hash签名,以确保文件的完整性。

把一个程序编译连接成可执行程序后,在别人的电脑上发现找不到其所依赖的库了,那么怎么办呢?首先我们自然想到把其所依赖的库相应的版本拷贝到目标计算机上面,可是……当你在拼命寻找那个可执行文件的assembly manifests文件的时候,却突然发现找不到了,在执行目录下面明明只有一个exe文件(或者是动态库等)。是不是没有生成呢?显然不会,原来是资源连接器把那个assembly manifests文件连接到了可执行文件里面了;不信,你可以用你的vc++打开一个可执行文件看看,在其资源项里面就有一个叫做RT_MANIFEST的项目。这个里面就是二进制标示的manifests文件。那么根据这里面提供的要求,将相应版本的依赖文件(一般就是CRT运行库)拷贝到系统目录Windows/WinSxS/,记住一般会是连带着一个特殊命名的目录一起拷贝到那个文件夹下,比如CRT的运行库就是WinSxS/x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50608.0_x-ww_b7acac55有这样一个目录,其标注了此库的版本号以及签名等信息,以防止多个版本重名时不能复制到同一WinSxS目录下。

这样就搞定了么?如果是以前,那么一切都解决了,系统会在这个目录下面找到这个运行库,可是现在单单这样可不行,系统可是要找到这个运行库的assembly manifests文件,并且对比强文件名之后才能加载,所以所以千万别忘了把相应的manifests文件拷贝到/WinSxS/Manifests目录下面。 当然,这样在目标的系统文件夹下面打动干戈,自然有些过于暴动了,还好,Windows还为我们提供了一种私有查找方式。这种方式会在前面的位置找不到合适库的时候在本地文件夹下面找。所以你只要把之前的库以及那个manifests文件一起拷贝到你的应用程序的路径下面,就可以使用啦。

根据MSDN的说明,在本地查找并加载遵循一下规则: 在应用程序本地文件夹中查找名为 <assemblyName>.manifest 的清单文件。在此示例中,加载程序试图在 appl.exe 所在的文件夹中查找 Microsoft.VC80.CRT.manifest。如果找到该清单,加载程序将从应用程序文件夹中加载 CRT DLL。如果未找到 CRT DLL,加载将失败。 尝试在 appl.exe 本地文件夹中打开文件夹 <assemblyName>,如果存在此文件夹,则从中加载清单文件 <assemblyName>.manifest。如果找到该清单,加载程序将从 <assemblyName> 文件夹中加载 CRT DLL。如果未找到 CRT DLL,加载将失败。 最后,我想补充的一点是,在你的VC++安装目录下面的“Microsoft Visual Studio 8/VC/redist”目录下,有着所有的提供发布的已经配备相应.manifest的库文件。所以你想要发布一个程序最简单最安全的做法(不用担心用户电脑是否包含你所需要的库)就是把这个目录下面的相应的库的文件夹和你的可执行文件放在一起发布。比如在X86平台下如果你的可执行文件用到了CRT库(废话么),那么就拷贝Microsoft Visual Studio 8/VC/redist/x86/Microsoft.VC80.CRT这个文件夹到你的程序所在的目录,一起发布,就万事大吉啦!


vc2008开发的程序的发布方式可以有5种方式:

1.采用静态链接到crt和MFC. 只要你拥有组成程序的所有源代码,你就可以采用这种方式, 这种方式除了程序变大一点,好处多多: 1) 不必重新发布vc2008基础库vcredist_x86.exe(安装到WinSxS).  

2) 不必产生,嵌入manifest.  

3) 也不把vc2008基础库放在程序所在目录.

2.exe(嵌入manifest) + vcredist_x86.exe确保程序正确产生并嵌入manifest文件,然后把程序和vcredist_x86.exe一起发布.用户先安装 vcredist_x86.exe(安装到WinSxS),然后程序就能正常运行了. 

3.exe(嵌入manifest) + 用到的基础库文件放到程序目录(包括库文件本身的manifest文件)确保程序正确产生并嵌入manifest文件,然后把程序用到的vc2008基础库相关文件复制到程序 所在目录,这种方式适用于用户没有安装过vcredist_x86.exe,一旦用户安装过vcredist_x86.exe, 若WinSxS中的相关文件遭到破坏,那么即使在程序目录放上所有用到的vc2008基础库,程序也跑 不起来;若WinSxS中的相关文件正常,那么程序目录下的相关文件就是多余的了,删掉它们程序也能 正常运行.

4.exe(自行编写manifest) + vcredist_x86.exe 

5.exe(自行编写manifest) + 用到的基础库文件放到程序目录(包括库文件本身的manifest文件)**


猜你喜欢

转载自blog.csdn.net/a33445621/article/details/72865694
今日推荐