Visual Studio 在 Windows 7 上将 WINVER/_WIN32_WINNT 设置为 Windows 8?

2023-11-30

我正在使用 Visual Studio 2012 在 Windows 7 x64 上执行一些测试。看起来 Microsoft 的工具链正在设置_WIN32_WINNT to 0x602 (_WIN32_WINNT_WIN8)。运行我们的测试程序结果The procedure entry point GetOverlappedResultEx could not be located in the dynamic link library KERNEL32.dll:

enter image description here

我有两个问题。首先,出于病态的好奇,微软为什么要设置_WIN32_WINNT为对执行环境无效的值?我可以理解用户是否想要这样做,但微软不能,因为它破坏了东西(q.v.).

二、我们如何设置WINVER or _WIN32_WINNT到象征性的“这个平台”?在本例中,“此平台”是 Windows 7。当我在 Windows Vista 上测试时,它将是一个不同的平台。当我在 Windows 8 上测试时,它将是另一个平台。当我在 ARM 开发人员提示下测试 Windows Phone 和 Windows Store 时,这将是另一个平台。


这个问题很容易重复。以下是步骤。我想任何拥有良好测试环境的人都已经完成了前八个步骤。

  1. 启动 Windows 7 x64 计算机
  2. 对 Windows 7 机器进行全面修补
  3. 安装 Visual Studio 2008
  4. 完全修补 Visual Studio 2008
  5. 安装 Visual Studio 2010
  6. 完全修补 Visual Studio 2010
  7. 安装 Visual Studio 2012
  8. 完全修补 Visual Studio 2012

Then:

  1. 在VS2008下创建一个空的“Hello World”项目
  2. Delete 一切 except hello_world.cpp(这应该留下 1 个解决方案文件、1 个项目文件、1 个源文件)
  3. 将其转换为VS2010
  4. 用VS2012打开

我可以发布 MCVE(一个空源文件)来安抚一些人。这似乎是浪费时间,因为问题出在工具链而不是源文件上。是一个空的main对于这个问题真的至关重要吗?错的WINVER and _WIN32_WINNT无论文件中有什么内容都会被设置。


我知道错误的根源。我们的代码最近进行了更改,以更好地支持Windows 8、Phone 8、Store 8、Server 2012、Windows 10、Phone 10、Store 10 和 Windows 通用平台。变化看起来像这样:

#if defined(CRYPTOPP_WIN32_AVAILABLE)
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
#  include <synchapi.h>
#  include <ioapiset.h>
#  define USE_WINDOWS8_API
# endif
#endif
...

#if defined(USE_WINDOWS8_API)
    BOOL result = GetOverlappedResultEx(GetHandle(), &m_overlapped, &m_lastResult, INFINITE, FALSE);
#else
    BOOL result = GetOverlappedResult(GetHandle(), &m_overlapped, &m_lastResult, FALSE);
#endif

讽刺的是,我们添加了USE_WINDOWS8_API,附加包含和调用GetOverlappedResultEx首先安抚工具。他们抱怨不推荐使用的函数并导致脏编译。脏编译给用户带来了治理、C&A 和 ST&E 问题。


我审核了代码以确保我们不会无意或错误地设置值。我验证我们在一个地方执行此操作,并且代码路径未激活,因为 Microsoft 的工具链正在将值设置为0x602:

#ifdef CRYPTOPP_WIN32_AVAILABLE
# ifndef _WIN32_WINNT
#  define _WIN32_WINNT 0x0400
# endif
#endif

这是一个相关的堆栈溢出问题:什么是WINVER?,但没有讨论如何设置为“这个平台”。

这是微软关于这个主题的文档:使用 Windows 标头 and 修改WINVER和_WIN32_WINNT。讽刺的是,他们并没有真正讨论 Windows 10、Windows Phone 10、Windows Store 10 或 Windows 通用平台的问题。


顺便说一句,GCC 有一个类似的-march=native基本上提供了“这个平台”。


“此平台”隐含在平台工具集中。 VS 2012 使用 Windows 8.0 SDK,默认为_WIN32_WINNT=0x0602(Windows 8)。 VS 2013 / 2015 使用 Windows 8.1 SDK,默认为_WIN32_WINNT=0x0603(Windows 8.1)。如果您使用 VS 2015 和 Windows 10 SDK,则默认为_WIN32_WINNT=0x0A00(Windows 10)。

这样做主要是为了 Windows 应用商店/UWP 应用程序的利益,这些应用程序需要最新的值_WIN32_WINNT正确构建。对于 Windows 10,_WIN32_WINNT值不会在各个版本之间更新,因此您可以配置要使用的并行 Windows 10 SDK。请参阅Visual C++ 团队博客了解详情。

对于 Windows 桌面应用程序(又名经典 Win32),您应该在构建配置中明确设置支持的操作系统版本。通常这是在pch.h或其他全局头文件,但也可以通过构建命令行/makefile/vcxproj 完成:

#include <WinSDKVer.h>
#define _WIN32_WINNT 0x0600 // Windows Vista SP2 or later
#include <SDKDDKVer.h>

or

#include <WinSDKVer.h>
#define _WIN32_WINNT 0x0601 // Windows 7 or later
#include <SDKDDKVer.h>

Windows 8.x SDK 可以面向 Windows Vista SP2、Windows 7、Windows 8.0、Windows 8.1 或更高版本。

如果您需要 Windows XP SP3 或 Windows Server 2003 SP2 支持,则必须使用选择 Windows 7.1A SDK 的替代平台工具集设置。看这个帖子有关差异的一些注释。

See 使用 Windows 标头 and 这篇博客文章

请记住,VS 2015 本身不支持针对 Windows 7 RTM,仅支持 Windows 7 Service Pack 1。

对于具体情况GetOverlappedResultEx,我在代码中使用以下模式,支持为下层 Windows 7 以及 UWP/Windows Store 进行构建。

    HANDLE hEvent = CreateEventEx( nullptr, nullptr,
        CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE );

...

    // Read and verify header
    OVERLAPPED request = {};
    request.hEvent = hEvent;

    bool wait = false;
    if( !ReadFile( hFile, ..., &request ) )
    {
        DWORD error = GetLastError();
        if ( error != ERROR_IO_PENDING )
            return HRESULT_FROM_WIN32( error );
        wait = true;
    }

    DWORD bytes;
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
    BOOL result = GetOverlappedResultEx( hFile, &request, &bytes, INFINITE, FALSE );
#else
    if ( wait  )
        (void)WaitForSingleObject( hEvent, INFINITE );

    BOOL result = GetOverlappedResult( hFile, &request, &bytes, FALSE );
#endif

然后,我为每个支持的平台提供静态库的多个版本。请记住,WACK 工具会检查您的 EXE/DLL 导入和导出表,并将标记任何不受支持的 API。因此,您无法选择运行时,并且必须仅引用“Windows 8”版本中支持的 API。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Visual Studio 在 Windows 7 上将 WINVER/_WIN32_WINNT 设置为 Windows 8? 的相关文章

随机推荐