visual-c++ - español - windows driver kit windows 10
advertencia C4996: ''GetVersionExW'': se declaró obsoleto (3)
Si bien GetVersionEx fue declarado obsoleto, si arroja un manifiesto de compatibilidad adecuado declarando la compatibilidad con Windows 8.1 y Windows 10, GetVersionEx devolverá el número de versión correcto. Uso GetVersionEx para detectar Windows 8 o superior, y dado que Windows 8 es la última versión de Windows que no requiere que un manifiesto devuelva la versión de Windows adecuada, mi código funciona bien independientemente de si la API devuelve Windows 6.2, 6.3, 6.4 (para primeras previsualizaciones de Windows 10), o 10.0.
Con todo lo dicho, Microsoft desaprobó esta API en parte debido al mal uso de la misma. Tomemos como ejemplo este intento de detectar Windows XP o superior:
BOOL IsXPOrGreater;
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osver);
if((osver.dwMajorVersion >= 5) && (osver.dwMinorVersion >=1) IsXPOrGreater = TRUE;
else IsXPOrGreater = FALSE;
Esta muestra devolvería TRUE en Windows XP, Server 2003, 7, 8 y 8.1, pero devolvería FALSE en Windows Vista o 10. Agregar una línea solucionaría esto:
BOOL IsXPOrGreater;
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osver);
if((osver.dwMajorVersion >= 5) && (osver.dwMinorVersion >=1) IsXPOrGreater = TRUE;
else if(osver.dwMajorVersion >= 6) IsXPOrGreater = TRUE;
else IsXPOrGreater = FALSE;
Esta muestra funcionaría correctamente porque sabe que si la versión principal es 6 o mayor, es mayor que XP.
Estoy trabajando en VS 2013 en Win 8.1. ¿Cómo resolver esta advertencia?
puede desactivar esta advertencia y usar GetVersionEx de todos modos agregando:
#pragma warning(disable : 4996)
La pregunta básica es "¿por qué llamas GetVersionExW
en primer lugar?" La respuesta a esa pregunta determina qué debe hacer en su lugar.
La advertencia de obsolescencia está ahí para darles a los desarrolladores un aviso sobre el cambio de comportamiento de aplicación que comenzó en Windows 8.1. Consulte el libro de recetas de compatibilidad de Windows y Windows Server: Windows 8, Windows 8.1 y Windows Server 2012 . En resumen, esa función no devuelve lo que crees que devuelve por defecto.
Históricamente, las comprobaciones de versiones del sistema operativo mal escritas son la principal fuente de errores de aplicación para las actualizaciones del sistema operativo Windows. Ha habido varios enfoques diferentes para tratar de mitigar este problema (la versión de AppVerifier mentira, la API VerifyVersionInfo
, etc.), y esta es la más agresiva hasta la fecha.
Los VersionHelpers.h
mencionados en los comentarios están en el SDK de Windows 8.1 que viene con Visual Studio 2013. No son una API nueva; son solo un código de utilidad que hace uso de la API VerifyVersionInfo
introducida en Windows 2000. Estas funciones son para hacer comprobaciones de estilo "Debe ser tan alto para montar este viaje", que son la clase de verificaciones de versión que con mayor frecuencia están mal escritas. El código es bastante simple. Por ejemplo, la prueba IsWindowsVistaSP2OrGreater
es:
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);
}
No necesita usar VersionHelpers.h
ya que podría hacer este tipo de código usted mismo, pero son convenientes si ya está utilizando el compilador VS 2013. Para juegos, tengo un artículo ¿Qué hay en un número de versión? que usa VerifyVersionInfo
para hacer el tipo de comprobaciones razonables que uno debe hacer para la implementación del juego.
Tenga en cuenta que si usa VS 2013 con el conjunto de herramientas de la plataforma
v120_xp
para apuntar a Windows XP, en realidad utilizará el SDK de Windows 7.1A y#include <VersionHelpers.h>
no funcionará. Por supuesto, puede utilizarVerifyVersionInfo
directamente.
El otro uso principal de GetVersionExW
son los registros de diagnóstico y la telemetría. En este caso, una opción es continuar usando esa API y asegurarse de tener las entradas de manifiesto correctas en su aplicación para garantizar resultados razonablemente precisos. Consulte Manifiesto de locura para obtener detalles sobre lo que hace aquí para lograrlo. Lo más importante a tener en cuenta es que a menos que actualice rutinariamente su código, eventualmente dejará de obtener información completamente precisa en una versión futura del sistema operativo.
Tenga en cuenta que se recomienda que ponga la sección
<compatibility>
en un manifiesto incrustado, ya sea que se preocupe o no por los resultados deGetVersionEx
como la mejor práctica general. Esto permite que el sistema operativo aplique automáticamente futuras correcciones de aplicación basadas en saber cómo se probó originalmente la aplicación.
Para los registros de diagnóstico, otro enfoque que podría ser un poco más robusto es tomar el número de versión de una DLL del sistema como kernel32.dll
utilizando GetFileVersionInfoW
. Este enfoque tiene una gran desventaja: no intente analizar sintácticamente, hacer comparaciones o hacer suposiciones de código en función de la versión del archivo que obtenga de esta manera; solo escríbelo en alguna parte . De lo contrario, corre el riesgo de VerifyVersionInfo
a VerifyVersionInfo
el mismo problema de comprobación de la versión del sistema operativo defectuoso que se resuelve mejor con VerifyVersionInfo
. Esta opción no está disponible para aplicaciones de Windows Store, aplicaciones de Windows Phone, etc., pero debería funcionar para aplicaciones de escritorio 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;
}
Si hay algún otro motivo por el que llama a GetVersionExW
, probablemente no debería llamarlo. La comprobación de un componente que podría faltar no debe vincularse a una verificación de versión. Por ejemplo, si su aplicación requiere Media Foundation, debe establecer un "Debe ser tan alto para usar este control de viaje" como el VersionHelpers.h IsWindowsVistaOrGreater
para el despliegue, pero en el tiempo de ejecución debe usar un enlace explícito a través de LoadLibrary
o LoadLibaryEx
para informar una error o utilice una alternativa si MFPLAT.DLL
no se encuentra.
Los enlaces explícitos no son una opción para las aplicaciones de la Tienda Windows. Windows 8.x resuelve este problema en particular al tener un stub
MFPLAT.DLL
yMFStartUp
devolverá E_NOTIMPL. Consulte "¿Quién movió mi [Windows Media] Cheese"?
Otro ejemplo: si su aplicación desea usar Direct3D 11.2 si está disponible y si no usa DirectX 11.0, debería usar establecer una IsWindowsVistaSP2OrGreater
mínima IsWindowsVistaSP2OrGreater
para la implementación tal vez usando el D3D11InstallHelper . Luego, en tiempo de ejecución, crearías el dispositivo DirectX 11.0 y, si falla, reportarías un error. Si obtiene un ID3D11Device
, entonces consultaría QueryInterface
para un ID3D11Device2
que, si tiene éxito, significa que está utilizando un sistema operativo compatible con DirectX 11.2. Ver Anatomía de Direct3D 11 Crear dispositivo .
Si esta aplicación hipotética de Direct3D es compatible con Windows XP, utilizaría una barra de despliegue de IsWindowsXPSP2OrGreater
o IsWindowsXPSP3OrGreater
, y luego en tiempo de ejecución usará enlaces explícitos para tratar de encontrar el D3D11.DLL
. Si no estuviera presente, recurriría a utilizar Direct3D 9, ya que establecemos la barra mínima, sabemos que DirectX 9.0c o posterior siempre está presente.
El punto clave aquí es que en la mayoría de los casos, no debe usar GetVersionEx
.
Tenga en cuenta que con Windows 10 ,
VerifyVersionInfo
y obtener el sello de la versión del archivo medianteGetFileVersionInfo
para kernel32.lib ahora están sujetos al mismo comportamiento basado en el manifiesto comoGetVersionEx
(es decir, sin el GUID manifiesto para Windows 10, devuelve resultados como si la versión del sistema operativo fuera 6.2 en lugar de 10.0).Para las aplicaciones de Windows universales en Windows 10, puede obtener una nueva WinRT API AnalyticsInfo para obtener una cadena de sello de versión para registros de diagnóstico y telemetría.