C ++ Cómo detectar Windows 10

Hace muchos años que escribí una herramienta de auditoría de PC y la he mantenido actualizada. Una de las funciones básicas es informar la versión de Windows que se ejecuta en la PC que se está auditando para la cual siempre he usado la llamada a GetVersionEx.

Esto funciona hasta e incluye Windows 8, pero no es compatible con Windows 10 y, de hecho, Windows 10 devuelve 8.2 al igual que Windows 8. Microsoft no parece haber introducido nada como un reemplazo directo, lo que sugiere que compruebe las características específicas requeridas en lugar de mirar el sistema operativo, pero para el propósito de la auditoría realmente deseo el nombre del sistema operativo.

El ‘escáner’ es un progtwig en C ++ que debe ejecutarse en cuentas no privilegiadas, por lo que no creo que haya leído otra sugerencia: recoger la versión de una DLL del sistema, como kernel32.dll, funcionará, ya que estas carpetas generalmente no son accesibles a los usuarios.

¡Cualquier otra sugerencia / pensamiento es bienvenida!

GetVersion y GetVersionEx fueron reemplazados por varias funciones auxiliares de versión . El que quiere es IsWindows10OrGreater . Se pueden encontrar en VersionHelpers.h .

IsWindows10OrGreater solo está disponible en el último SDK / Visual Studio 2015. Sin embargo, puede usar IsWindowsVersionOrGreater en el caso general. Por ejemplo, en mi caja 7 obtengo TRUE para IsWindowsVersionOrGreater (6, 0, 0) .

Recuerde que los parámetros que toma esta función se relacionan con el número de comstackción de Windows y NO con el nombre comercial. Entonces Windows 8 es construir 6.2. Windows 7 es 6.0, etc.

A partir de Windows 8.1, GetVersion() y GetVersionEx() están sujetos a la manifestación de la aplicación:

Con el lanzamiento de Windows 8.1, el comportamiento de la API GetVersionEx ha cambiado en el valor que devolverá para la versión del sistema operativo. El valor devuelto por la función GetVersionEx ahora depende de cómo se manifiesta la aplicación.

Las aplicaciones no manifestadas para Windows 8.1 o Windows 10 devolverán el valor de versión del sistema operativo Windows 8 (6.2). Una vez que se manifiesta una aplicación para una versión determinada del sistema operativo, GetVersionEx siempre devolverá la versión para la que se manifiesta la aplicación en futuras versiones. Para manifestar sus aplicaciones para Windows 8.1 o Windows 10, consulte Orientación de su aplicación para Windows .

Las funciones más nuevas de Version Helper son simplemente wrappers para VerifyVersionInfo() . Comenzando en Windows 10, ahora está sujeto a la manifestación también:

Windows 10: VerifyVersionInfo devuelve falso cuando lo VerifyVersionInfo aplicaciones que no tienen un manifiesto de compatibilidad para Windows 8.1 o Windows 10 si el parámetro lpVersionInfo está configurado para que especifique Windows 8.1 o Windows 10, incluso cuando la versión actual del sistema operativo sea Windows 8.1 o Windows 10. Específicamente, VerifyVersionInfo tiene el siguiente comportamiento:

  • Si la aplicación no tiene manifiesto, VerifyVersionInfo comporta como si la versión del sistema operativo fuera Windows 8 (6.2).
  • Si la aplicación tiene un manifiesto que contiene el GUID que corresponde a Windows 8.1, VerifyVersionInfo comporta como si la versión del sistema operativo fuera Windows 8.1 (6.3).
  • Si la aplicación tiene un manifiesto que contiene el GUID que corresponde a Windows 10, VerifyVersionInfo comporta como si la versión del sistema operativo fuera Windows 10 (10.0).

Las funciones de Version Helper utilizan la función VerifyVersionInfo , por lo que el comportamiento IsWindows8Point1OrGreater e IsWindows10OrGreater se ven afectados de forma similar por la presencia y el contenido del manifiesto.

Para manifestar sus aplicaciones para Windows 8.1 o Windows 10, consulte Orientación de su aplicación para Windows .

Para obtener la verdadera versión del sistema operativo, independientemente de la manifestación, Microsoft sugiere consultar la versión de archivo de una DLL del sistema:

Obtener la versión del sistema

Para obtener el número de versión completo del sistema operativo, llame a la función GetFileVersionInfo en una de las DLL del sistema, como Kernel32.dll , luego llame a VerQueryValue para obtener el \\StringFileInfo\\\\ProductVersion de la información de la versión del archivo.

Otra forma es usar RtlGetVersion() , NetServerGetInfo() o NetWkstaGetInfo() lugar. Todos ellos informan una versión precisa del sistema operativo y no están sujetos a manifestación (¿todavía?).

Necesitaba esto para trabajar en una versión anterior del comstackdor VS, y más en un marco Qt. Así es como lo logré.

Agregue este archivo GetWinVersion.h a su proyecto de Qt:

 #ifndef GETWINVERSION #define GETWINVERSION #include  #ifdef Q_OS_WIN #include  #include  float GetWinVersion() { OSVERSIONINFO osvi; ZeroMemory( &osvi, sizeof(OSVERSIONINFO) ); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); return GetVersionEx( &osvi ) ? (float)osvi.dwMajorVersion + ((float)osvi.dwMinorVersion/10) : 0.0 ; } #endif //Q_OS_WIN #endif // GETWINVERSION 

Agregue el enlace requerido en su archivo pro o prma qmake:

 msvc: LIBS += -lKernel32 

Implemente la función auxiliar como tal (note que SystemInfo utilizado aquí es una clase personalizada de la mía, pero se entiende la idea …):

 #include "GetWinVersion.h" SystemInfo info; #ifdef Q_OS_WIN info.setPlatform( SystemInfo::WINDOWS ); switch(QSysInfo::windowsVersion()) { case QSysInfo::WV_32s: info.setOsName( L"3.1" ); info.setOsVersion( 3.1 ); break; case QSysInfo::WV_95: info.setOsName( L"95" ); info.setOsVersion( 4.0 ); break; case QSysInfo::WV_98: info.setOsName( L"98" ); info.setOsVersion( 4.1 ); break; case QSysInfo::WV_Me: info.setOsName( L"Me" ); info.setOsVersion( 4.9 ); break; case QSysInfo::WV_NT: info.setOsName( L"NT" ); info.setOsVersion( 4.0 ); break; case QSysInfo::WV_2000: info.setOsName( L"2000" ); info.setOsVersion( 5.0 ); break; case QSysInfo::WV_XP: info.setOsName( L"XP" ); info.setOsVersion( 5.1 ); break; case QSysInfo::WV_2003: info.setOsName( L"2003" ); info.setOsVersion( 5.2 ); break; // Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition case QSysInfo::WV_VISTA: info.setOsName( L"Vista" ); info.setOsVersion( 6.0 ); break; // Windows Vista, Windows Server 2008 case QSysInfo::WV_WINDOWS7: info.setOsName( L"7" ); info.setOsVersion( 6.1 ); break; // Windows 7, Windows Server 2008 R2 case QSysInfo::WV_WINDOWS8: info.setOsName( L"8" ); info.setOsVersion( 6.2 ); break; // Windows 8, Windows Server 2012 // These cases are never reached due to Windows api changes // As of Qt 5.5, this not accounted for by QSysInfo::windowsVersion() //case QSysInfo::WV_WINDOWS8_1: info.setOsName( L"8.1" ); info.setOsVersion( 6.3 ); break; // Windows 8.1, Windows Server 2012 R2 //case QSysInfo::WV_WINDOWS10: info.setOsName( L"10" ); info.setOsVersion( 10.0 ); break; // Windows 10, Windows Server 2016 default: // On Windows 8.1 & 10, this will only work when the exe // contains a manifest which targets the specific OS's // you wish to detect. Else 6.2 (ie. Win 8.0 is returned) info.setOsVersion( GetWinVersion() ); if( info.osVersion() == 6.3f ) // Windows 8.1, Windows Server 2012 R2 info.setOsName( L"8.1" ); else if( info.osVersion() == 10.0f ) // Windows 10, Windows Server 2016 info.setOsName( L"10" ); else info.setOsName( L"UNKNOWN" ); } info.setOsBits( IsWow64() ? 64 : 32 ); #else ... 

Ahora aquí está la clave real. Debe adjuntar un archivo de manifiesto a su ejecutable que “orientará” las versiones recientes de Windows, de lo contrario no podrá detectarlas (consulte los documentos de MS: https://msdn.microsoft.com/en-us/library/windows). /desktop/ms724451%28v=vs.85%29.aspx ). Aquí hay un manifiesto de ejemplo para hacer esto:

 < ?xml version="1.0" encoding="UTF-8" standalone="yes"?>                  

Y aquí hay un lote para adjuntar el manifiesto:

 set exeFile=MyApp.exe set manifestFile=MyApp.manifest set manifestExe=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\x64\mt.exe "%manifestExe%" -manifest "%manifestFile%" -outputresource:"%exeFile%" 

En teoría, puede usar qmake para ejecutar ese último bit adjuntando el manifiesto. No tuve suerte con los ejemplos que encontré, y simplemente “engañé” con este lote por ahora …

Use la siguiente función:

 double getSysOpType() { int ret = 0.0; NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW); OSVERSIONINFOEXW osInfo; *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); if (NULL != RtlGetVersion) { osInfo.dwOSVersionInfoSize = sizeof(osInfo); RtlGetVersion(&osInfo); ret = osInfo.dwMajorVersion; } return ret; } 

Devolverá la versión de Windows como un doble (7, 8, 8.1, 10).