12

是否可以在 VC++10.0 中链接 VC6 的 MSVCRT.DLL?

默认情况下,它似乎与 MSVCR100.DLL 链接,但我不想重新分发另一个 DLL(MSVCRT.DLL 已在我支持的每个操作系统中可用)。

==编辑==

澄清一下:我的应用程序是一个纯 C 应用程序,它进行 WinAPI 调用。我知道做 C++ 需要 C++ 运行时,默认情况下它没有捆绑在 Windows 中(而且很可能无论如何都必须匹配编译器)。我的问题是关于纯 C 的使用,以及我所针对的最早版本的 Windows 中存在的 CRT 函数。

4

4 回答 4

14

(您可以在底部找到执行摘要或 TL;DR)

重要提示:此答案仅指官方 Microsoft 工具链,不是已知链接到msvcrt.dll. 但我怀疑微软是否会倾向于支持该工具链;)

简短的回答:不!

甚至不要尝试使用 Visual C++ 2010 来完成这项任务。

有一个官方和受支持的方法:使用独立的 WDK,如果您需要您的应用程序链接到msvcrt.dll!

永远不应尝试使用与 CRT 头文件和库不匹配的编译器工具链。按照 Microsoft 的意图使用工具链,而不是您创建的拼凑而成。不要混搭。使用 Microsoft 提供给您的内容。但是使用它(不要害怕 FUD)。

可用于链接的最新 WDK msvcrt.dll(7600.16385.1) 使用cl.exe版本 15.00.30729.207。这大致对应于 Visual C++ 2008 附带的编译器!以后的 WDK 将链接到他们需要的 Visual C++ 版本的 CRT 。

msvcrt.dll您会发现,Windows XP 或 Windows 7并不是Visual C++ 6.0(甚至是最新版本的 VC6)中包含的原始DLL。

这也已在其他答案中正确说明。那里没有惊喜。

但是,与其他答案所暗示的相反msvcrt.dll,您将在现代系统上找到VC6 CRT 允许链接到原始 VC6 CRT 的程序继续工作。即使在今天。这是一份合同。并且升级msvcrt.dll到系统 DLL 进一步验证了该合同。

一点历史背景

Microsoft 内部使用的工具链有点类似于在 Windows 8 WDK 之前提供的 WDK。我将专门写这些并统一使用术语 WDK(或独立 WDK),即使在 Vista WDK 之前它们被称为 DDK。

来自OSR的好人,他们似乎可以访问 Windows 源代码或可以访问的人,在几年前我参加的一次研讨会上证实,WDK 曾经是内部使用的工具链的精简版本,用于围绕时间(〜2005年)。类似的提示可以从 MSFT 自己的 Larry OstermanAlex Ionescu 在 tinykrnl 上的早期作品中找到,最近版本的“Windows Internals”的合著者。BCZ 可能暗指build -cZ,这是我在此处描述的 WDK 的常用调用。

在这种情况下有趣的原因是:所有独立的 WDK 都允许您创建msvcrt.dll默认链接的可执行文件。独立的WDKmsvcrt.dll是CRT,就像 Visual C++ 2010 的.msvcr100.dll

还应注意,工具链与 Visual Studio 工具链一起更新。例如,在 3790.1830 WDKcl.exe报告中,它与 Visual C++ 2003 大致相当:

C:\WINDDK\3790.1830\bin\x86>cl /version
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.4035 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

对于 6001.18002 WDK(最新支持 Windows 2000!)与 Visual C++ 2005 大致相当:

C:\WINDDK\6001.18002\bin\x86\x86>cl/version
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.278 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

对于 7600.16385.1 WDK,它与 Visual C++ 2008 相当。

独立 WDK

WDK 版本从 XP 开始,直到(包括)Windows 7 SP1 不需要 Visual Studio。他们带有自己的工具链。

Windows XP 之前的版本需要 Visual C++ 来构建任何东西。如果我没记错的话,VC6 适用于 Windows 2000 DDK。

从 Windows 8 WDK 开始的版本再次需要 Visual C++,并且与它的集成比以往任何时候都更加紧密(包括向导,甚至用于调试和某些驱动程序特定任务的扩展)。这也是为什么当您使用各自的 WDK 时,它们会链接到各自工具链的 CRT。

在独立的 WDK 时代,人们尝试使用 Visual Studio 来封装 WDK 构建过程并非闻所未闻——这正是 DDKWizard 和VisualDDK的真正原因。有些人甚至使用了微软推荐的不受支持的方法,使用Visual Studio 工具链构建了他们的驱动程序。那些不受支持的方法大致相当于您正在尝试的方法。所以不要。

build.exe无论如何,使用 WDK和sources等等的构建过程makefile是麻烦和限制的。例如,要从当前目录或其父目录之外的任何源文件构建,您必须编写自己的 NMake 规则。毕竟build.exe是基于 NMake 的构建的包装器。您的本地makefile.inc将包含在 WDK/DDK 提供的全局中。

为什么msvcrt.dll官方支持链接

如前所述,msvcrt.dll独立 WDK 支持链接。

这也很好。事实上,文件中的USE_MSVCRT=1语句sources正是具有这种效果。见这里。引用 7600.16385.1 WDK 文档:

USE_MSVCRT

使用USE_MSVCRT宏来指示构建实用程序使用 DLL 中的多线程运行时库进行构建。

句法

USE_MSVCRT = 1

[...]

注意 您永远不应该列出Msvcrt.libMsvcrtd.libTARGETLIBS. 但是,您可以Ntdll.libTARGETLIBS.

如果微软不支持这条路径,为什么还要提供呢?正确,他们不会!

事实上,WDK (XP..7 SP1) 一直在使用系统 DLL msvcrt.dll作为其 CRT。

注意事项

主要有一个警告。SEH 的实现方式随着时间的推移随着更新的 Visual C++ 版本而改变。由于来自独立 WDK 的工具链与特定的 Visual C++ 版本密切对应,因此它们继承了各自的 SEH 处理。

例如,当您使用 Windows 7 SP1 WDK 以 Windows 7 为目标时USE_MSVCRT=1,它会静态导入_except_handler4_common. 例如,该功能在 Windows Server 2003 上不可用。因此,尝试在目标版本之前的 Windows 版本上运行此类应用程序可能会失败。因此,在这种情况下,您正在冒险进入“不受支持的领域”,并且所有免责声明都适用。但是,您可以选择使用此处概述的方法,即链接到msvcrt_win2000.obj和(在 Vista 和 7 WDK 中可用)来实现您想要的(二进制)向后兼容性级别msvcrt_winxp.objmsvcrt_win2003.obj

好吧,另一方面,如果您决定设置,WINVER=0x0601您也不应该惊讶地发现生成的可执行文件从 kernel32.dll(或其他系统 DLL)导入函数,而这些函数在 Windows XP 上不可用。那么为什么期望不同的语义msvcrt.dll呢?

作为另一个旁注:即使已检查的构建(通常被认为对应于调试构建)也链接到msvcrt.dll,而不是其调试版本对应!因为“已检查”是指保留断言的事实;它不是指 CRT 的特定配置,例如“发布”或“调试”。假设msvcrt.dll在独立 WDK 中无法进行调试构建意味着它在某种程度上不是那些 WDK的C 运行时,这是对检查构建的含义的简单误解。

还有一个小警告。msvcrt.dll例如,如果您使用Windows 7 WDK 来实现与. 所以不要指望它支持发布时不可用的功能。

系统DLL:msvcrt.dll

msvcrt.dll几年前被提升为系统 DLL 的状态,这意味着它与其他 Visual C++ CRT 不同,它包含在系统中(并且可以从字面上依赖),您需要为其安装相应的可再发行包。这也是另一个答案中引用的 Raymond Chen 博客文章的要点。

由于独立的 WDK (XP..7 SP1) 默认链接到msvcrt.dll作为它们的 CRT,因此没有反对它的客观论据。当然意见不一。

回答”

不幸的是,自从我第一次发表评论以来,这个答案已经发生了很大变化,使 FUD 长期存在,并试图从所谓的权威来源中断章取意地引用。它还链接到原始 (MSFT) 来源 - 经过仔细检查 - 不支持它们所链接的支持声明。


几年前,微软的 Raymond Chen 曾在博客上发表过这篇文章。从他的博客Windows 不是 Microsoft Visual C/C++ 运行时交付渠道

一个与所有版本的 Visual C++ 兼容的 DLL 是维护的噩梦……在某些时候,决定放弃并声明它是操作系统 DLL,仅供操作系统组件使用

强调我的。再想一想,你真的在​​写 Windows 自带的东西吗?将支持的文件添加到您的安装程序或链接 CRT 的静态版本,而不是依赖于微软十多年前在编译器兼容性方面放弃的系统组件,是否有那么难?

好的,所以 2010 年 2 月是十多年前(写这个答案的时间:2016 年 3 月)?因为那是 7600.16385.1 WDK 的发布日期,它正式支持链接到msvcrt.dll.

Raymond 的其他声明可能与微软最初的意图相符,但他甚至承认他们放弃了这一点,并将其提升为系统 DLL。

此外,将真正古老的历史 (Windows 9x) 与支持使用甚至不支持 Windows 9x 的独立 WDK 的建议混合在一起是非常不诚实的。Raymond 描述的历史背景是 W2K 之前和非 NT。我上面描述的背景是指 Windows 的 NT 血统,我只知道独立的 DDK/WDK(和更新的)从实践中,所以我不知道在此之前它是如何或应该是什么。

话虽如此:不要将他的博客与 Microsoft 的官方文档混淆,尽管在他的博客上可以找到很多珍品,而且我多年来一直是狂热的读者。

尽管是十多年前的事了,但msvcrt.dllWindows 2000 (SP4) 中的版本信息显示:

Description:    Microsoft (R) C Runtime Library
Product:        Microsoft (R) Visual C++
Prod version:   6.10.9844.0
File version:   6.10.9844.0

...与雷蒙德的介绍性声明相反。

只有在 Windows XP 中才会更改为:

Description:    Windows NT CRT DLL
Product:        Microsoft« Windows« Operating System

令人惊讶的是,仍有多少人否认这一决定。

在之前的一些评论之后,可以公平地假设这完全是针对我的。

好吧,我并不否认发布 Windows 8 WDK 所做出的决定。但这并没有“取消发布”官方支持链接的独立 WDK,msvcrt.dll也没有“取消记录”可以在其各自的官方文档中找到的内容。

嘿,如果您处于奢侈的位置,只需要支持 Windows 7 或 8 及更新版本,或者类似的东西,我觉得很酷。但是,我也必须支持早期的 Windows 版本,因此我将充分利用微软为这些 Windows 版本提供的官方工具。可以是集成了适当 SDK 的 Visual C++ 2005,也可以是独立的 WDK。


那些人给“Visual C++ 产品团队带来了极大的悲痛”

该声明引用了 Raymond Chen 的上述博客文章,但将 Raymond 的声明脱离了上下文,特别是脱离了时间上下文。悲伤是由于人们尝试了提问者想要做的事情 - 更糟糕的是:触及msvcrt.dll. 那是在 W2K 之前。它不是(也不会是)由使用官方工具链(如 Microsoft 的独立 WDK)引起的。


现代版本的 Windows 中的 msvcrt 版本从未在相应版本的 Windows SDK 中提及。

虽然现代应该是合格的,但“Windows SDK”的使用表明它指的是从“平台 SDK”重命名后的所有 Windows SDK。我倾向于欣然相信这一点。但是海报忽略了独立的 Windows WDK(以及在此之前的 DDK),它们不仅提到它,而且还msvcrt.dll用作它们的 CRT。它们Microsoft 的官方工具链,针对内核和用户模式开发。


Microsoft 使用可能会或可能不会公开的当前工具链更新 CRT DLL(例如,在发布 Windows Media Player 补丁时)。

这是正确的。msvcrt.dll不断更新,因为它已被提升为系统 DLL。这就是使用 WDK 时可以依赖的合同。他们不会仅仅因为他们正在修补msvcrt.dll.


您可以指望他们没有使用古老的 WDK 编译器和库在 Windows 中构建 msvcrt DLL

我什至不确定这一点,但 2010 年的官方工具链并不是我称之为古老的东西。此外,由于微软同时放弃了对 XP 和 2003 的支持,他们只需要支持 Vista 及更高版本。使用最新的 Visual C++ 版本肯定会更容易,它直接为从 Windows 8 开始的 WDK 提供编译器和工具。

(为什么古老?因为WDK团队也不喜欢人们使用他们的编译器链接msvcrt,并删除了8.0版本的漏洞以阻止那些“聪明”的人)。

哦,真的,Doron 真的在链接的论坛帖子中这么说吗?好吧,不:

win7 wdk 构建部署成功,因为您链接到 Windows CRT (msvcrt.dll)。我们不想让第 3 方再这样做 ,所以我们在 win8 wdk 中删除了该功能。它仍然适用于向后兼容。虽然它可能会成功部署,但可能会有 whck 徽标检查以确保您使用正确的 CRT

(强调我的)

该声明是关于微软改变立场的“政治决定”(也是官方决定)。“不再”实际上意味着这仅在 Windows 8 WDK 中发生了变化。第一个与 Visual C++ 再次集成的现代 WDK(自 Windows 2000 DDK 起)。因此,由于 WDK 已从独立工具链降级为与给定 Visual C++ 版本集成的扩展,因此新要求一点也不奇怪。

顺便说一句,基于 Windows 8 WDK 和更新版本的争论也是不诚实的,因为有关msvcrt.dll用作 CRT 的独立 WDK 的建议早于该政策更改。将导致升级为msvcrt.dll系统DLL的历史与升级的时代混为一谈也是不诚实的。


词汇表

  • CRT == C/C++ 运行时
  • 3790.1830 == Windows Server 2003 Service Pack 1 (SP1) 驱动程序开发工具包 (DDK)
  • 6001.18002 == 适用于 Windows Server 2008/Vista 的 Windows Driver Kit SP1
  • 7600.16385.1 == Windows Driver Kit 版本 7.1.0(支持 Windows 7、Windows Vista、Windows XP、Windows Server 2008 R2、Windows Server 2008、Windows Server 2003)

TL;博士

这个答案相反,使用微软自己的和未更改的工具链是完全可以的,例如独立的 WDK,它支持msvcrt.dll“本机”链接到 (XP..7 SP1)。它甚至记录在这些工具链附带的文档中(除非您决定不安装它或闭上眼睛:))。

您“仅”必须确保在构建时针对正确的 Windows 版本(本质上与定义正确的WINVER. 但是对于其他系统 DLL(例如kernel32.dlluser32.dll...)也可以这样说。

但是,使用自 2002 年以来的任何Visual C++ 进行链接msvcrt.dll 必然会产生麻烦。不要混搭。只需使用匹配那些特定 Visual C++ 版本的 CRT。

于 2016-03-23T22:33:05.610 回答
10

这不是 VC6 运行时。它是与 Windows 而非 Visual Studio 捆绑在一起的 MSVCRT.DLL 的系统副本。正如您通过检查文件大小可以看到的那样,每个新版本的 Windows 都会获得一个新版本的 MSVCRT.DLL。

您可以使用 Windows 驱动程序工具包针对 MSVCRT.DLL 的系统副本进行编译。请注意,此 DLL 仅供“系统级组件”使用。什么是系统级组件?嗯,一个司机。或者,例如,文本服务:

http://blogs.msdn.com/b/tsfaware/archive/2008/01/17/visual-studio-2008-issues.aspx

如果您正在构建文本服务 DLL……我建议您安装 Vista(或 XP)DDK 并改用 DDKWizard。DDK 带有自己的 C/C++ 编译器,该编译器使用操作系统附带的 C 运行时库(并且不会导致其他应用程序出现问题)......

更多信息:

http://kobyk.wordpress.com/2007/07/20/dynamically-linking-with-msvcrtdll-using-visual-c-2005/

一个问题出现了,微软是做什么的?他们将应用程序部署到各种 Windows 环境中。查看 Windbg 的依赖项表明它使用的是 MSVCRT.DLL,而不是较新的 CRT 之一。Microsoft 的新网络监视器 3.1 也使用 MSVCRT.DLL。Windows 桌面搜索也使用旧的、可信赖的 CRT。

所有这些新应用程序如何使用老式 CRT?他们还没有使用老式的、不受支持的 Visual C++ 6.0,是吗?嗯,不。答案比较复杂,可以在 Windows Driver Kit (WDK) 中找到。

更新:Windows 8 Driver Kit 引入了一个新的基于 MSBuild 的构建系统,它不再链接到 MSVCRT.DLL 的系统副本。但是,使用 Windows 7 驱动程序工具包构建的二进制文件仍可在 Windows 8 和 Windows 10 上运行。

MSVCRT.DLL 仍随 Windows 10 提供以实现向后兼容性,因此它的文件版本为 7.0.#####。仍在积极开发的组件,例如 user32.dll,其文件版本为 10.0.#####。

于 2012-10-14T23:46:12.020 回答
7

一个普通的“Petzold 风格”Win32 程序只需要 msvcrt.dll 中的几个函数。就我而言,我经常需要浮点格式化例程,例如 _sntprintf()。而且这些功能的功能不太可能发生变化。出于这个原因,我创建了一个“msvcrt-light.lib”导入库来替代我包含在 MSVC 项目中的标准库。( http://www.tu-chemnitz.de/~heha/hs/msvcrt-light.zip/ )

对于成熟的 C++ 程序,msvcrt-light.lib 可能根本不适合。如上所述使用 DDK。

于 2013-09-25T12:20:04.133 回答
0

这需要跨主要编译器版本的 CRT 兼容性,微软试图适应(例如向 VC6SP2 运行时添加一个 VC5 堆)但最终放弃并引入了今天使用的 msvcrxx.dll。如果你查看 CRT 源代码,你会发现很多 #ifndef _SYSCRT,这就是微软的 msvcrt.dll 和你的编译器在生成代码时使用的那个的区别。

几年前,微软的 Raymond Chen 曾在博客上发表过这篇文章。从他的博客Windows 不是 Microsoft Visual C/C++ 运行时交付渠道

一个与所有版本的 Visual C++ 兼容的 DLL 是维护的噩梦……在某些时候,决定放弃并声明它是操作系统 DLL,仅供操作系统组件使用

强调我的。再想一想,将支持的文件添加到您的安装程序或链接 CRT 的静态版本,而不是依赖于微软十多年前在编译器兼容性方面放弃的系统组件有那么难吗?

令人惊讶的是,仍有多少人否认这一决定。那些人给“Visual C++ 产品团队带来了极大的痛苦”,如果你一直惹恼他们,如果他们有时像他们在 Windows XP中所做的那样让很多 VC6 应用程序崩溃而激怒你,我也不会感到惊讶. 很多人没有遵循 Windows 2000 应用程序开发者指南,而是将设置/游戏保存在 Program Files 文件夹中。我们都知道 Windows Vista 发布时的美好结局。

顺便说一句,dll不是VC6的。在系统中使用旧的 dll 会自动使 Microsoft 的安全开发生命周期失败。(https://blogs.msdn.microsoft.com/oldnewthing/20100607-00/?p=13793/#10020962)。您不会真的期望 Microsoft 使用 VC6 来编译它的现代产品,是吗?

现代版本的 Windows 中的 msvcrt 版本从未在相应版本的 Windows SDK 中提及。无论您使用何种编译器版本或 CRT lib 版本,它很可能与您客户机器上的大多数 DLL 版本不匹配。Microsoft使用可能会或可能不会公开的当前工具链更新 CRT DLL(例如,在发布 Windows Media Player 补丁时)。你可以指望他们没有使用古老的 WDK 编译器和库在 Windows 中构建 msvcrt DLL(为什么古老?因为WDK 团队也不喜欢人们使用他们的编译器链接 msvcrt,并删除了版本 8.0 中的漏洞阻止那些“聪明”的人)。

于 2012-04-16T02:35:36.340 回答