关于 c :App 不能与 VS 2008 SP1 DLL 一起运行,以前的版本适用于 RTM 版本

关于 c :App 不能与 VS 2008 SP1 DLL 一起运行,以前的版本适用于 RTM 版本

App does not run with VS 2008 SP1 DLLs, previous version works with RTM versions

自从我们从 Visual Studio 6 切换到 Visual Studio 2008 以来,我们一直在使用 MFC90.dll 和 msvc[pr]90.dll 以及私有并行配置中的清单文件,以便不用担心版本或将它们安装到系统中。

在 SP1 之前,它运行良好(在我们的开发人员机器上仍然运行良好)。既然我们已经在 SP1 后进行了一些测试,我从昨天早上就开始拔头发了。

首先,我们的 NSIS 安装程序脚本从 redist 文件夹中提取 dll 和清单文件。这些不再正确,因为该应用仍链接到 RTM 版本。

所以我将 _BIND_TO_CURRENT_VCLIBS_VERSION=1 的定义添加到我们所有的项目中,以便它们将使用 redist 文件夹中的 SP1 DLL(或新服务包出现时的后续)。我花了几个小时才找到这个。

我已经从编译中仔细检查了中间文件夹中生成的清单文件,它们正确列出了 9.0.30729.1 SP1 版本。我已经两次和三次检查取决于一台干净的机器:它都链接到本地?? dll,没有错误。

运行应用程序仍然出现以下错误:

The application failed to initialize properly (0xc0150002). Click on OK to terminate the application.

我在 google 或 microsoft 上进行的所有搜索都没有找到与我的特定问题相关的任何内容(但有回溯到 2005 年的错误消息)。

有人用SP1遇到过类似的问题吗?

选项:

  • 找到问题并修复它,使其正常工作(首选)

  • 安装redist

  • 挖出旧的 RTM dll 和清单文件并删除 #define 以使用当前的。 (我在较早的安装程序版本中获得了它们,因为 Microsoft 将它们从您的 redist 文件夹中删除!)

编辑:我尝试在关闭定义的情况下重新构建(链接到 RTM dll),只要 RTM dll 安装在文件夹中,它就可以工作。如果将 SP1 dll 放入,则会收到以下错误:

c:\\Program Files\\...\\...\\X.exe

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

没有其他人必须处理这个问题吗?

编辑:只是为了笑,我在我的测试机器上下载并运行了 VS2008SP1 的 vcredist_x86.exe。有用。使用 SP1 DLL。还有我的 RTM 链接应用程序。但不是在 SP1 之前工作的私有并行分发中。


上周我自己也解决了这个问题,现在我觉得自己有点专家了;)

我 99% 确定并非所有 dll 和静态库都使用 SP1 版本重新编译。你需要把

1
2
#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

进入您正在使用的每个项目。对于每个实际大小的项目,很容易忘记一些没有重新编译的小库。

还有更多的标志来定义要绑定的版本;它记录在 http://msdn.microsoft.com/en-us/library/cc664727(v=vs.90).aspx 上。作为上述行的替代方法,您还可以将

1
#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\\' 下查看。检查右侧的 \\'version\\' 属性是否为 \\'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 表示法。下表显示了一些可能的情况:

1
2
3
4
5
6
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 时,这些情况的结果是:

  • 情况一:出现弹窗,提示:"程序入口点XYZXYZ不能在动态链接库中定位"。

  • 情况 2:运行 .exe 时似乎没有任何反应,但在 Windows\\'"Event Viewer / Application log" 中记录了以下事件:

    为 "C:\\\\\\\\Path\\\\\\\\file.exe" 生成激活上下文失败。清单或策略文件 "C:\\\\\\\\Path\\\\\\\\Microsoft.VC90. CRT.MANIFEST" 在第 4 行。在清单中找到的组件标识与请求的组件的标识不匹配。参考是 Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"。定义是微软

  • 情况 3:一切正常。这是 remicles2 的解决方案。

  • 情况4:应该这样做。遗憾的是,正如 Roel 所指出的,它可能很难实现。

现在,我的情况(我认为它与 crashmstr\\'s 相同)是 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\\ 的项目和所有依赖的 .lib 项目中使用 _BIND_TO_CURRENT_VCLIBS_VERSION 标志。
  • 对于公共程序集,这不是必需的,因为 Windows 会自动从 SxS 目录中选择正确版本的 .DLL。

另一个查看 exe 和 dll 清单的好工具是 Manifest View,它在 XP 的全新安装上无法运行,因为它依赖于 9.0.21022。


我只记得我用来找出哪些静态库行为不端的另一个技巧:通过字符串\\'21022\\' 的静态库\\'grep\\'。但是,不要使用像wingrep 这样的\\'普通\\' grep 工具,因为它们不会向您显示这些字符串(他们认为这是一个二进制文件并查找原始的非Unicode 字符串)。使用资源工具包中的 \\'strings\\' 实用程序(我认为现在在 Russinovich 网站上)。那将通过二进制文件进行 grep 所以你让这个\\'strings\\'遍历你的整个源代码树,你会看到包含对错误清单(或其中包含错误版本的清单)的引用的二进制文件(dll 和静态库)。


对于您的第三个选项,您可能可以在您的开发机器上的 C:\\\\\\\\WINDOWS\\\\\\\\WinSxS 目录中找到 9.0.21022 版本的 DLL 和清单。如果可以,那么您可以设置自己的 redist 目录并使用您的应用程序安装这些文件。

或者,您可以使用随 Visual Studio 提供的 9.0.30729.1 并伪造随应用安装的清单,以报告它提供 9.0.21022 DLL,而不是 9.0.30729.1。运行时链接器似乎并不介意。有关详细信息,请参阅此博客,该博客对解决这些问题非常有帮助。

两种解决方法都解决了我在使用 VS2008 Express 将 DLL 部署为私有程序集时遇到的问题。

Roel 的答案是您的第一个选项("正确修复"),但如果您依赖于一个依赖于 9.0.21022 的库(因此您的清单列出了两个版本),如果您不想运行 vcredist_x86.exe,那么第三个选项可能是唯一的选择。


推荐阅读

    linux命令jdk版本?

    linux命令jdk版本?,系统,官网,地方,网上,状态,位置,官方网站,服务,发行,命令

    vim运行linux命令?

    vim运行linux命令?,系统,工作,信息,地址,命令,标准,时间,情况,工具,基础,linu

    linux命令切换到d盘?

    linux命令切换到d盘?,管理,电脑,软件,术语,代码,系统,产品,信息,时报,标准,电

    linux下并行运行命令?

    linux下并行运行命令?,系统,服务,工作,命令,环境,网络,暂停,文件,脚本,参数,l

    linux下并行运行命令?

    linux下并行运行命令?,系统,服务,工作,命令,环境,网络,暂停,文件,脚本,参数,l

    linux命令切换到d盘?

    linux命令切换到d盘?,管理,电脑,软件,术语,代码,系统,产品,信息,时报,标准,电

    linux命令怎样降版本?

    linux命令怎样降版本?,系统,服务,管理,数据,电脑,地方,风险,档案,软件,通用,l

    linux命令切换到界面?

    linux命令切换到界面?,密码,系统,暂停,状态,终端,工具,地方,环境,信息,数字,

    linux命令行后台运行?

    linux命令行后台运行?,服务,状态,标准,暂停,命令,后台,连续,地方,工作,方法,l

    脚本运行linux命令?

    脚本运行linux命令?,系统,环境,工具,工作,位置,底部,代码,发行,官网,终端,lin

    linux进程运行命令?

    linux进程运行命令?,系统,工作,状态,地址,信息,进程,基础,命令,管理,软件,lin

    linux显示运行命令?

    linux显示运行命令?,系统,服务,状态,信息,工具,数据,电脑,标准,管理,时间,如

    linux运行vim命令?

    linux运行vim命令?,系统,工具,官方网站,模式,基础,数据,代码,环境,入口,命令

    linux监控命令运行?

    linux监控命令运行?,系统,工作,地址,信息,工具,情况,标准,环境,命令,状态,lin

    linux中命令停止运行?

    linux中命令停止运行?,系统,代码,第一,命令,进程,指令,程序,方法,接线,硬盘,l

    linux查系统版本命令?

    linux查系统版本命令?,系统,信息,地址,名称,设备,命令,版本,电脑,软件,工具,

    linux自动运行命令?

    linux自动运行命令?,服务,系统,时间,代码,周期性,第一,命令,管理,在线,状态,l

    linux开启运行命令?

    linux开启运行命令?,系统,服务,工作,管理,状态,命令,标准,情况,环境,工具,lin

    linux运行wps命令?

    linux运行wps命令?,软件,官网,名称,时间,电脑,系统,工具,环境,项目,数据,wps

    linux运行cmd命令?

    linux运行cmd命令?,电脑,系统,状态,情况,环境,命令,单位,管理,设备,数据,电脑