web-dev-qa-db-fra.com

C ++ Comment détecter Windows 10

J'ai écrit un outil d'audit PC il y a de nombreuses années et je l'ai mis à jour. L'une des fonctions de base consiste à signaler la version de Windows exécutée sur le PC en cours d'audit pour laquelle j'ai toujours utilisé l'appel GetVersionEx.

Cela fonctionne jusqu'à Windows 8 inclus, mais n'est pas pris en charge sous Windows 10 et en effet, Windows 10 renvoie 8.2 tout comme Windows 8. Microsoft ne semble pas avoir introduit quoi que ce soit comme un remplacement direct suggérant à la place que vous vérifiez les fonctionnalités spécifiques requises plutôt que de regarder le système d'exploitation, mais aux fins de l'audit, je veux en fait le nom du système d'exploitation.

Le 'scanner' est un programme C++ qui doit s'exécuter sous des comptes non privilégiés, donc je ne pense pas qu'une autre suggestion que j'ai lue - choisir la version d'un système DLL comme kernel32.dll fonctionnera car ces dossiers ne sont généralement pas accessibles aux utilisateurs.

Toutes autres suggestions/pensées sont les bienvenues!

21
user1169502

GetVersion et GetVersionEx ont été remplacées par diverses fonctions d'assistance de version . Celui que vous voulez est IsWindows10OrGreater . Ils peuvent être trouvés dans VersionHelpers.h .

IsWindows10OrGreater est uniquement disponible dans le dernier SDK/Visual Studio 2015. Vous pouvez utiliser IsWindowsVersionOrGreater dans le cas général cependant. Par exemple, sur ma case 7, je reçois VRAI pour IsWindowsVersionOrGreater (6, 0, 0) .

N'oubliez pas que les paramètres que cette fonction prend se rapportent au numéro de build de Windows et NON au nom marketing. Windows 8 est donc la version 6.2. Windows 7 est 6.0, etc.

14
Robinson

Utilisez la fonction suivante:

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;
}

Il renverra la version Windows sous forme de double (7, 8, 8.1, 10).

4
Michael Haephrati

J'avais besoin de cela pour travailler sur une ancienne version du compilateur VS, et plus encore dans un cadre Qt. Voici comment j'ai accompli cela.

Ajoutez ce fichier GetWinVersion.h à votre projet Qt:

#ifndef GETWINVERSION
#define GETWINVERSION

#include <QtGlobal>

#ifdef Q_OS_WIN

#include <windows.h>
#include <stdio.h>

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

Ajoutez le lien requis dans votre fichier pro ou pri qmake:

msvc: LIBS += -lKernel32

Implémentez la fonction d'assistance comme ceci (notez que SystemInfo utilisé ici est une classe personnalisée à moi, mais vous avez l'idée ...):

#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
...

Voici maintenant la vraie clé. Vous devez joindre un fichier manifeste à votre exe qui "ciblera" les versions récentes de Windows, sinon vous ne pourrez pas les détecter (voir la documentation MS: https://msdn.Microsoft.com/en-us /library/windows/desktop/ms724451%28v=vs.85%29.aspx ). Voici un exemple de manifeste pour ce faire:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Assembly xmlns="urn:schemas-Microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity 
        name="MyOrg.MyDept.MyAppName" 
        version="1.0.0.0" 
        processorArchitecture="x86" 
        type="win32" />
    <compatibility xmlns="urn:schemas-Microsoft-com:compatibility.v1"> 
        <application> 
            <!-- Windows 10 --> 
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>      
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>          
        </application> 
    </compatibility>
</Assembly>

Et voici un lot pour attacher le manifeste:

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 théorie, vous pouvez utiliser qmake pour exécuter ce dernier bit en attachant le manifeste. Je n'ai pas eu de chance avec les exemples que j'ai trouvés, et j'ai juste "triché" avec ce lot pour l'instant ...

1
BuvinJ