【问题标题】:Why does MSVC use system DLL's rather than toolkit DLL's?为什么 MSVC 使用系统 DLL 而不是工具包 DLL?
【发布时间】:2020-08-17 21:43:27
【问题描述】:

我安装了 MSVC 141 / VS2017 和两个 Windows 工具包(10.0.17763.0 和 10.0.18362.0)。但是,我真的可以选择使用哪个 ucrtbase.dll 吗? VS 自动使用我的系统 DLL,尽管文件系统的 Microsoft SDKs / Windows Kits 部分中有几个变体。它还使用这些系统 DLL 来构建我的 Windows SDK 版本 10.0.17763.0 或 10.0.18362.0 的程序。

'Demo.exe' (Win32): Loaded 'C:\Users\business\source\repos\YZ\x64\Release\AEC_Demo.exe'. Symbols loaded.
'Demo.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. Symbols loaded.
'Demo.exe' (Win32): Loaded 'C:\Windows\System32\kernel32.dll'. Symbols loaded.
'Demo.exe' (Win32): Loaded 'C:\Windows\System32\KernelBase.dll'. Symbols loaded.
'Demo.exe' (Win32): Loaded 'C:\Users\business\source\repos\YZ\x64\Release\AEC_DLL.dll'. Symbols loaded.
'Demo.exe' (Win32): Loaded 'C:\Windows\System32\ucrtbase.dll'. 
:

这里是 dll.intermediate.manifest(我还构建了 Demo.exe 使用的 DLL):

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

这是 Demo.exe 的清单:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

【问题讨论】:

标签: c++ windows dll


【解决方案1】:

在 Win32 上运行时;您必须将 Win32 dll 加载到您的进程中,否则无法正常工作。与某些其他操作系统不同,在 Windows 上,系统调用不是 ABI 表面,而是 Windows 提供的共享库 (dll),例如 kernel32.dll、user32.dll、gdi32.dll 和 advapi32.dll。 kernelbase.dll 和 ntdll.dll 是 kernel32.dll 的依赖。

ucrtbase.dll 是另一个具有类似规则的操作系统组件,只是不是强制性组件。如果您使用此组件,您将链接到该组件的操作系统版本,并且来自一个操作系统的版本将无法在另一个操作系统上运行。

对于这些 dll,将 SDK 版本设置为较低会更改您链接的版本(通过链接较旧的 .lib 文件),但不会更改您运行的版本。除非您动态调用它们,否则尝试使用不在旧版本 Windows 中的函数是行不通的。

【讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • @Joshua,了解加载这些 DLL 是一回事。 RbMm 的 cmets 在指向清单时很有用。但我仍然觉得我无法控制加载哪些 DLL。什么是最失败的安全/傻瓜证明/否决方式可供选择,以便我可以轻松控制正在使用的 DLL?我如何prevent certain System DLL's being loaded explicitly
  • @JuliusBaer:你不知道。针对另一个版本的系统 dll 运行的唯一方法是在使用该版本的系统 dll 的 Windows 版本上运行。
【解决方案2】:

您可能会发现 Windows 和 Linux 之间的一个关键区别。

在 Linux 上,通常的方法是编译软件以在本地机器上运行,并且就在本地机器上。如果该二进制文件在其他地方运行,这通常是一个奇迹。因此,您将程序链接到系统库。另一方面,Linux 交叉编译简直就是一场噩梦。

另一方面,Windows 构建实际上总是交叉编译。您针对 Windows SDK 进行编译,而不是针对恰好存在于您的特定构建机器上的系统库。这些 SDK 反过来支持许多 Windows 版本,直到指定的版本,但通常也支持旧版本。 UCRT 可以追溯到 Windows 8.1 IIRC,即使您使用 10.0.18362.0 SDK。

现在,如果您测试您的可执行文件,您现在可以将您的 PC 用作运行时环境。同一台 PC 安装了一个或多个 Windows SDK 并不重要。毕竟,您不能指望最终用户安装 SDK。它是 Windows,典型的用户不是工程师。因此,您的可执行文件使用系统 DLL。如果您需要 Visual C++ DLL,则需要在安装程序中包含 VC++ 可再发行组件。

【讨论】:

  • "如果您需要 Visual C++ DLL,则需要在安装程序中包含 VC++ 可再发行组件" 可能是这样,我实际上认为我只需要在我的发布版本中使用它们来修复错误。
  • @JuliusBaer,正如我在移至聊天的评论中提到的,您可以覆盖“已知 DLL”,例如“ucrtbase.dll”,系统通常使用预映射的部分对象,使用“.local”重定向,或者,如果可执行文件具有清单(在这种情况下,.local 重定向被忽略),则使用依赖程序集。
猜你喜欢
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 2012-03-09
  • 2010-09-15
相关资源
最近更新 更多