警告 C4996:“GetVersionExW":已宣布弃用 [英] warning C4996: 'GetVersionExW': was declared deprecated

查看:72
本文介绍了警告 C4996:“GetVersionExW":已宣布弃用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Win 8.1 开发 VS 2013.如何解决这个警告?

解决方案

基本问题是你为什么首先调用 GetVersionExW?";这个问题的答案决定了你应该做什么.

弃用警告是为了让开发人员提前了解从 Windows 8.1 开始的 appcompat 行为更改.请参阅 Windows 和 Windows Server 兼容性手册:Windows 8、Windows 8.1 和 Windows Server 2012.简而言之,该函数不会返回您认为默认返回的内容.

从历史上看,编写不当的操作系统版本检查是 Windows 操作系统升级的 appcompat 错误的主要来源.有许多不同的方法试图缓解这个问题(AppVerifier 版本谎言、VerifyVersionInfo API 等),这是迄今为止最积极的.

注释中提到的VersionHelpers.h是Visual Studio 2013自带的Windows 8.1 SDK.它们不是新的API;它们只是利用了 Windows 2000 中引入的 VerifyVersionInfo API 的实用程序代码.这些函数用于执行你必须这么高才能骑这个"样式检查,这是最常写得不好的版本检查类.代码非常简单.例如,IsWindowsVistaSP2OrGreater 测试是:

VERSIONHELPERAPIIsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor){OSVERSIONINFOEXW osvi = {};osvi.dwOSVersionInfoSize = sizeof(osvi);DWORDLONG const dwlConditionMask = VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),VER_MINORVERSION, VER_GREATER_EQUAL),VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);osvi.dwMajorVersion = wMajorVersion;osvi.dwMinorVersion = wMinorVersion;osvi.wServicePackMajor = wServicePackMajor;return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;}版本帮助APIIsWindowsVistaSP2OrGreater(){返回 IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);}

您不需要使用 VersionHelpers.h,因为您可以自己编写此类代码,但是如果您已经在使用 VS 2013 编译器,它们会很方便.对于游戏,我有一篇文章版本号中有什么?它使用 VerifyVersionInfo 进行游戏部署应该进行的合理检查.

<块引用>

请注意,如果您使用带有 v120_xp 平台工具集的 VS 2013 来面向 Windows XP,您实际上将使用 Windows 7.1A SDK 和 #include 不起作用.你当然可以直接使用VerifyVersionInfo.

GetVersionExW 的另一个主要用途是诊断日志和遥测.在这种情况下,一种选择是继续使用该 API 并确保您的应用程序中有正确的清单条目,以确保结果相当准确.请参阅Manifest Madness,了解您在此处为实现这一目标所做的工作的详细信息.要记住的主要事情是,除非您定期更新代码,否则您最终将无法在未来版本的操作系统中获得完全准确的信息.

<块引用>

请注意,无论您是否关心 GetVersionEx 的结果作为一般最佳实践,建议您将 部分放在嵌入式清单中.这允许操作系统根据应用最初的测试方式自动应用未来的 appcompat 修复.

对于诊断日志,另一种可能更可靠的方法是使用 GetFileVersionInfoW 从系统 DLL 中获取版本号,例如 kernel32.dll.这种方法有一个主要的警告:不要尝试根据您通过这种方式获得的文件版本进行解析、比较或进行代码假设;把它写在某个地方.否则,您可能会重新创建相同的错误操作系统版本检查问题,而使用 VerifyVersionInfo 可以更好地解决该问题.此选项不适用于 Windows 应用商店应用、Windows 手机应用等,但适用于 Win32 桌面应用.

#include #include #include <内存>#pragma 注释(lib,version.lib")bool GetOSVersionString( WCHAR* 版本, size_t maxlen ){WCHAR 路径[_MAX_PATH] = {};如果(!GetSystemDirectoryW(路径,_MAX_PATH))返回假;wcscat_s(路径,L\\kernel32.dll");////基于本文的示例代码//http://support.microsoft.com/kb/167597//双字句柄;#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );#别的DWORD len = GetFileVersionInfoSizeW( path, &handle );#万一如果(!len)返回假;std::unique_ptrbuff(新(std::nothrow)uint8_t[len]);如果(!buff)返回假;#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )#别的if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )#万一返回假;VS_FIXEDFILEINFO *vInfo = nullptr;单位信息大小;if ( !VerQueryValueW( buff.get(), L\\", reinterpret_cast( &vInfo ), &infoSize ) )返回假;如果(!信息大小)返回假;swprintf_s(版本,maxlen,L%u.%u.%u.%u",HIWORD( vInfo->dwFileVersionMS ),LOWORD(vInfo->dwFileVersionMS),HIWORD(vInfo->dwFileVersionLS),LOWORD(vInfo->dwFileVersionLS));返回真;}

如果您调用 GetVersionExW 有其他原因,您可能不应该调用它.检查可能丢失的组件不应与版本检查相关联.例如,如果您的应用程序需要 Media Foundation,则您应该设置您必须如此高才能参加此骑行检查";类似于用于部署的 VersionHelpers.h IsWindowsVistaOrGreater,但在运行时您应该使用通过 LoadLibraryLoadLibaryEx 的显式链接来报告错误或使用回退如果未找到 MFPLAT.DLL.

<块引用>

显式链接不是 Windows 应用商店应用程序的选项.Windows 8.x 解决了这个问题存根 MFPLAT.DLLMFStartUp 的特殊问题将返回 E_NOTIMPL.请参阅谁动了我的 [Windows Media] Cheese"?

另一个示例:如果您的应用程序想要使用 Direct3D 11.2(如果可用),否则使用 DirectX 11.0,您可以使用设置一个 IsWindowsVistaSP2OrGreater 最低部署栏,可能使用 D3D11InstallHelper.然后在运行时,您将创建 DirectX 11.0 设备,如果它失败,您将报告错误.如果您获得 ID3D11Device,那么您将 QueryInterface 用于 ID3D11Device2,如果成功,则意味着您使用的是支持 DirectX 11.2 的操作系统.请参阅剖析 Direct3D 11 创建设备.

如果这个假设的 Direct3D 应用程序支持 Windows XP,您将使用 IsWindowsXPSP2OrGreaterIsWindowsXPSP3OrGreater 的部署栏,然后在运行时使用显式链接来尝试查找D3D11.DLL.如果它不存在,您将回退到使用 Direct3D 9——因为我们设置了最低标准,我们知道 DirectX 9.0c 或更高版本始终存在.

这里的重点是,在大多数情况下,您不应该使用 GetVersionEx.

<块引用>

请注意,对于 Windows 10VerifyVersionInfo 和通过 GetFileVersionInfo 获取 kernel32.lib 的文件版本标记现在受相同清单的约束基于 GetVersionEx 的行为(即没有 Windows 10 的清单 GUID,它返回的结果就像操作系统版本是 6.2 而不是 10.0).

<块引用>

对于 Windows 10 上的通用 Windows 应用程序,您可以使用新的 WinRT API AnalyticsInfo 获取诊断日志和遥测的版本戳字符串.

I am working on VS 2013 in Win 8.1. How to solve this warning?

解决方案

The basic question is "why are you calling GetVersionExW in the first place?" The answer to that question determines what you should do instead.

The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn't return what you think it returns by default.

Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There've been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.

The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing "You must be this high to ride this ride" style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = {};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    DWORDLONG        const dwlConditionMask = VerSetConditionMask(
        VerSetConditionMask(
        VerSetConditionMask(
            0, VER_MAJORVERSION, VER_GREATER_EQUAL),
               VER_MINORVERSION, VER_GREATER_EQUAL),
               VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

    osvi.dwMajorVersion = wMajorVersion;
    osvi.dwMinorVersion = wMinorVersion;
    osvi.wServicePackMajor = wServicePackMajor;

    return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}

VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
    return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}

You don't need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What's in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.

Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you'll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won't work. You can of course use VerifyVersionInfo directly.

The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.

Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.

For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.

#include <Windows.h>
#include <cstdint>
#include <memory>

#pragma comment(lib, "version.lib" )

bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
    WCHAR path[ _MAX_PATH ] = {};
    if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
        return false;

    wcscat_s( path, L"\\kernel32.dll" );

    //
    // Based on example code from this article
    // http://support.microsoft.com/kb/167597
    //

    DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
    DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
    if ( !len )
        return false;

    std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
    if ( !buff )
        return false;

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
    if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
        return false;

    VS_FIXEDFILEINFO *vInfo = nullptr;
    UINT infoSize;

    if ( !VerQueryValueW( buff.get(), L"\\", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
        return false;

    if ( !infoSize )
        return false;

    swprintf_s( version, maxlen, L"%u.%u.%u.%u",
                HIWORD( vInfo->dwFileVersionMS ),
                LOWORD(vInfo->dwFileVersionMS),
                HIWORD(vInfo->dwFileVersionLS),
                LOWORD(vInfo->dwFileVersionLS) );
    
    return true;
}

If there is some other reason you are calling GetVersionExW, you probably shouldn't be calling it. Checking for a component that might be missing shouldn't be tied to a version check. For example, if your application requires Media Foundation, you should set a "You must be this high to ride this ride check" like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.

Explicit linking is not an option for Windows Store apps. Windows 8.x solves this particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL. See "Who moved my [Windows Media] Cheese"?

Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you'd use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you'd create the DirectX 11.0 device and if it fails, you'd report an error. If you obtain a ID3D11Device, then you'd QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.

If this hypothetical Direct3D application supports Windows XP, you'd use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn't present, you'd fall back to using Direct3D 9--since we set the minimum bar, we know that DirectX 9.0c or later is always present.

They key point here is that in most cases, you should not use GetVersionEx.

Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).

For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

这篇关于警告 C4996:“GetVersionExW":已宣布弃用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆