自从我们从Visual Studio 6切换到Visual Studio 2008以来,我们一直在使用MFC90.dll和msvc [pr] 90.dlls以及私有并排配置中的清单文件,以免担心版本或者将它们安装到系统中.
在SP1之前,这个工作正常(在我们的开发人员机器上仍能正常工作).现在我们已经在SP1之后做了一些测试,从昨天早上起我一直在拉头发.
首先,我们的NSIS安装程序脚本从redist文件夹中提取dll和manifest文件.这些不再正确,因为应用程序仍然链接到RTM版本.
所以我为_BIND_TO_CURRENT_VCLIBS_VERSION=1
所有项目添加了define,以便他们在redist文件夹中使用SP1 DLL(或随后的新服务包出来).我花了好几个小时才找到这个.
我已经从编译中检查了中间文件文件夹中生成的清单文件,并正确列出了9.0.30729.1 SP1版本.我有双重和三重检查取决于一台干净的机器:它都链接到本地dll没有错误.
运行应用程序仍会收到以下错误:
应用程序无法正确初始化(0xc0150002).单击"确定"以终止该应用程序.
我在谷歌或微软上所做的任何搜索都没有提出任何与我的具体问题相关的信息(但是这些错误消息可以追溯到2005年).
有没有任何一个与SP1有类似的问题?
选项:
找到问题并修复它,使它按预期工作(首选)
安装redist
挖掘出旧的RTM dll和清单文件,并删除#define以使用当前的文件.(我已经在早期的安装程序版本中使用它们,因为Microsoft会将它们从redist文件夹中删除!)
编辑:我尝试重新构建关闭定义(链接到RTM dll),只要RTM dll安装在文件夹中,它就可以工作.如果SP1 dll被删除,则会出现以下错误:
c:\ Program Files\...\...\X.exe
此应用程序无法启动,因为应用程序配置不正确.重新安装应用程序可能会解决此问题.
没有人不得不处理这个问题吗?
编辑:只是为了笑容,我下载并在我的测试机器上运行VS2008SP1的vcredist_x86.exe.它有效.使用SP1 DLL.我的RTM链接应用程序.但不是在SP1之前工作的私有并行分发.
我上周自己也在和这个问题作斗争,现在认为自己有点专家了;)
我99%确定不是所有的dll和静态库都是用SP1版本重新编译的.你需要把
#define _BIND_TO_CURRENT_MFC_VERSION 1 #define _BIND_TO_CURRENT_CRT_VERSION 1
进入您正在使用的每个项目.对于每个真实世界大小的项目,很容易忘记一些未重新编译的小型库.
有更多标志定义要绑定的版本; 它记录在http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx上.作为上述行的替代,您也可以放
#define _BIND_TO_CURRENT_VCLIBS_VERSION 1
它将绑定到所有VC库(CRT,MFC,ATL,OpenMP)的最新版本.
然后,检查嵌入式清单所说的内容.下载XM资源编辑器:http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.在解决方案中打开每个dll和exe.看看'XP Theme Manifest'.检查右侧的"版本"属性是否为"9.0.30729.1".如果它是'9.0.21022',一些静态库正在拉入旧版本的清单.
我发现在很多情况下,两个版本都包含在清单中.这意味着某些库使用sp1版本而其他库则不使用.
调试哪些库没有设置预处理程序指令的好方法:临时修改平台标头,以便在尝试嵌入旧清单时编译停止.打开C:\ Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.搜索'21022'字符串.在那个定义中,放置一些无效的东西(将'define'改为'blehbleh'左右).这样,当您编译_BIND_TO_CURRENT_CRT_VERSION
未设置预处理程序标志的项目时,您的编译将停止,您将知道您需要添加它们或确保它在任何地方都应用.
另外,请确保使用Dependency Walker,以便了解正在插入的dll.最简单的方法是在虚拟机上安装没有更新(仅SP2)的全新Windows XP副本.这样您就可以确定SxS文件夹中没有任何内容正在使用,而不是您提供的并排dll.
要理解这个问题,我认为重要的是要意识到涉及四个版本号:
(A)编译.exe的VC头文件的版本.
(B)嵌入在该.exe的资源部分中的清单文件的版本.默认情况下,此清单文件由Visual Studio自动生成.
(C)您在与.exe相同的目录中复制的VC .DLL(并行程序集的一部分)的版本.
(D)您在与.exe相同的目录中复制的VC清单文件的版本(并行程序集的一部分).
运行中有两个版本的VC 2008 DLL:
v1:9.0.21022.8
v2:9.0.30729.4148
为清楚起见,我将使用v1/v2表示法.下表显示了许多可能的情况:
Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D) ----------------------------------------------------------------------------- 1 | v2 | v1 | v1 | v1 2 | v2 | v1 | v2 | v2 3 | v2 | v1 | v2 | v1 4 | v2 | v2 | v2 | v2
在干净的Vista SP1安装上运行.exe时,这些情况的结果是:
情况1:显示弹出窗口,说:"程序入口点XYZXYZ无法位于动态链接库中".
情况2:运行.exe时似乎没有发生任何事情,但Windows"事件查看器/应用程序日志"中记录了以下事件:
第4行的清单或策略文件"C:\ Path\Microsoft.VC90.CRT.MANIFEST"中的"C:\ Path\file.exe".Error中的激活上下文生成失败.清单中找到的组件标识与标识不匹配请求的组件.参考是Microsoft.VC90.CRT,processorArchitecture ="x86",publicKeyToken ="1fc8b3b9a1e18e3b",type ="win32",version ="9.0.21022.8".定义是微软
情况3:一切似乎都很好.这是remicles2的解决方案.
情况4:这是应该如何完成的.遗憾的是,正如罗尔所指出的那样,实施起来可能相当困难.
现在,我的情况(我认为它与crashmstr的相同)是nr 1.问题是Visual Studio出于某种原因为v2生成客户端代码(A),但出于某种原因,生成v1清单档案(B).我不知道可以在哪里配置版本(A).
请注意,这整个解释仍然在私有程序集的上下文中.
更新:最后我开始了解发生了什么.显然,Visual Studio默认为v2生成客户端代码(A),这与我在某些Microsoft博客上读到的相反._BIND_TO_CURRENT_VCLIBS_VERSION标志仅选择生成的清单文件(B)中的版本,但在运行应用程序时将忽略此版本.
默认情况下,由Visual Studio 2008编译的.exe链接到最新版本的VC90 DLL.您可以使用_BIND_TO_CURRENT_VCLIBS_VERSION标志来控制将在清单文件中生成哪个版本的VC90库.这确实避免了情况2,在这种情况下,您收到错误消息"清单与所请求组件的标识不匹配".它还解释了为什么情况3工作正常,因为即使没有_BIND_TO_CURRENT_VCLIBS_VERSION标志,应用程序也链接到最新版本的VC DLL.
使用vcredist运行的公共并行程序集甚至更奇怪,将VC 9.0 DLL放在Windows SxS目录中.即使.exe的清单文件指出应该使用旧版本的DLL(在未设置_BIND_TO_CURRENT_VCLIBS_VERSION标志的情况下),Windows 默认会忽略此版本号!相反,除非使用"应用程序配置文件",否则Windows将使用较新的版本(如果存在于系统上).
我是唯一一个认为这令人困惑的人吗?
因此,在总结:
对于私有程序集,请在.exe的项目中使用_BIND_TO_CURRENT_VCLIBS_VERSION标志以及所有相关的.lib项目.
对于公共程序集,这不是必需的,因为Windows将自动从SxS目录中选择正确版本的.DLL.