Подтвердить что ты не робот

Предупреждение C4996: "GetVersionExW": объявлено устаревшим

Я работаю над VS 2013 в Win 8.1. Как решить это предупреждение?

4b9b3361

Ответ 1

Основной вопрос: "Почему вы вызываете GetVersionExW в первую очередь?" Ответ на этот вопрос определяет, что вы должны делать вместо этого.

Предупреждение об устаревании должно дать разработчикам хедз-ап об изменении поведения appcompat, которое началось в Windows 8.1. См. Поваренная книга совместимости с Windows и Windows Server: Windows 8, Windows 8.1 и Windows Server 2012. Короче говоря, эта функция не возвращает то, что, по вашему мнению, возвращает по умолчанию.

Исторически, плохо написанные проверки версий ОС являются основным источником ошибок appcompat для обновлений ОС Windows. Было несколько различных подходов к устранению этой проблемы (версия AppVerifier лежит, API VerifyVersionInfo и т.д.), И это наиболее агрессивно на сегодняшний день.

VersionHelpers.h, упомянутый в комментариях, содержится в SDK Windows 8.1, который поставляется с Visual Studio 2013. Они не являются новым API; это всего лишь код утилиты, который использует API VerifyVersionInfo, введенный обратно в Windows 2000. Эти функции предназначены для того, чтобы выполнять проверки типа "Вы должны быть такими, чтобы ездить на этой поездке", которые являются классом проверки версий, которые чаще всего бывают плохо написано. Код довольно прост. Например, тест IsWindowsVistaSP2OrGreater:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
    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);
}

Вам не нужно использовать VersionHelpers.h, поскольку вы могли бы просто сделать этот код самостоятельно, но они удобны, если вы уже используете компилятор VS 2013. Для игр у меня есть статья Что в номере версии?, который использует VerifyVersionInfo для выполнения разумных проверок, необходимых для развертывания игры.

Обратите внимание, что если вы используете VS 2013 с набором инструментов платформы v120_xp для целевой Windows XP, вы фактически будете использовать SDK Windows 7.1A, а #include <VersionHelpers.h> не будет работать. Конечно, вы можете напрямую использовать VerifyVersionInfo.

Другим основным использованием GetVersionExW являются диагностические журналы и телеметрия. В этом случае один из вариантов заключается в том, чтобы продолжать использовать этот API и убедиться, что у вас есть правильные записи манифеста в приложении, чтобы обеспечить достаточно точные результаты. Подробнее о том, что вы здесь делаете, см. Manifest Madness. Главное, чтобы вы имели в виду, что, если вы регулярно обновляете свой код, вы в конечном итоге перестанете получать точную информацию в будущей версии ОС.

Обратите внимание, что рекомендуется поместить раздел <compatibility> во встроенный манифест, независимо от того, насколько вы заботитесь о результатах GetVersionEx как общей лучшей практики. Это позволяет ОС автоматически применять будущие исправления appcompat, основываясь на знании того, как приложение было первоначально протестировано.

Для журналов диагностики другой подход, который может быть немного более надежным, - это захватить номер версии из системной DLL, например kernel32.dll, используя GetFileVersionInfoW. Этот подход имеет большой хаос: не пытайтесь разбираться, делать сравнения или делать допущения кода на основе версии файла, которую вы получаете таким образом; просто напишите где-нибудь. В противном случае вы рискуете воссоздать ту же самую проблему с проверкой версии ОС, которая лучше решается с помощью VerifyVersionInfo. Эта опция недоступна для приложений Windows Store, приложений для телефонов Windows и т.д., Но должна работать в настольных приложениях Win32.

#include <windows.h>
#include <stdint.h>
#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;
}

Если есть еще одна причина, по которой вы вызываете GetVersionExW, вы, вероятно, не должны ее вызывать. Проверка компонента, который может отсутствовать, не должна быть привязана к проверке версии. Например, если вашему приложению требуется Media Foundation, вы должны установить для этого развертывания "Это должно быть высоко, чтобы выполнить эту проверку езды", например VersionHelpers.h IsWindowsVistaOrGreater, но во время выполнения вы должны использовать явное соединение через LoadLibrary или LoadLibaryEx сообщить об ошибке или использовать резервную копию, если MFPLAT.DLL не найден.

Явное связывание не является вариантом для приложений Windows Store. Windows 8.x решает эту проблему. особая проблема с помощью заглушки MFPLAT.DLL и MFStartUp вернет E_NOTIMPL. См. "Кто переместил мой [Windows Media] сыр" ?

Другой пример: если ваше приложение хочет использовать Direct3D 11.2, если оно доступно, и в противном случае использует DirectX 11.0, вы должны использовать минимальную панель IsWindowsVistaSP2OrGreater для развертывания, возможно, используя D3D11InstallHelper, Затем во время выполнения вы должны создать устройство DirectX 11.0, и если он сбой, вы сообщите об ошибке. Если вы получите ID3D11Device, вы бы QueryInterface для ID3D11Device2, который, если он преуспеет, означает, что вы используете ОС, поддерживающую DirectX 11.2. См. Анатомия Direct3D 11 Создать устройство.

Если это гипотетическое приложение Direct3D поддерживает Windows XP, вы должны использовать панель развертывания IsWindowsXPSP2OrGreater или IsWindowsXPSP3OrGreater, а затем во время выполнения используйте явное соединение, чтобы попытаться найти D3D11.DLL. Если его нет, вы вернетесь к использованию Direct3D 9 - поскольку мы устанавливаем минимальную полосу, мы знаем, что DirectX 9.0c или более поздняя версия присутствует всегда.

Ключевым моментом здесь является то, что в большинстве случаев вы не должны использовать GetVersionEx.

Обратите внимание, что при Windows 10, VerifyVersionInfo и получении штампа версии файла через GetFileVersionInfo для kernel32.lib теперь подчиняется такому же основанному на манифестам поведению, что и GetVersionEx (т.е. без манифест GUID для Windows 10, он возвращает результаты, как если бы версия ОС была 6.2, а не 10.0).

Для универсальных приложений Windows в Windows 10 вы можете использовать новый WinRT API AnalyticsInfo, чтобы получить строку штампа версии для диагностических журналов и телеметрии.

Ответ 2

вы можете отключить это предупреждение и использовать GetVersionEx в любом случае, добавив:

#pragma warning(disable : 4996)