c ++ - GetVersionEx under Windows 8

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver en C ++ kode til at bestemme, hvilket OS det kører på. Jeg bruger GetVersionEx() API til at gøre det, og denne kode som en tutorial, men det synes ikke at håndtere Windows 8. Er der nogen der ved hvordan at rette den til at køre under Windows 8? [10]

Bedste reference


Ifølge flere kommentarer i MSDN fora og denne artikel er versionsnummeret til Windows 8 6,2 [11]


Dette er prøvekoden opdateret og testet i Windows 8 Developer Preview


#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

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

#define BUFSIZE 256

typedef void (WINAPI *PGNSI)(LPSYSTEM\_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);

BOOL GetOSDisplayString( LPTSTR pszOS)
{
   OSVERSIONINFOEX osvi;
   SYSTEM\_INFO si;
   PGNSI pGNSI;
   PGPI pGPI;
   BOOL bOsVersionInfoEx;
   DWORD dwType;

   ZeroMemory(&si, sizeof(SYSTEM\_INFO));
   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
   bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);

   if( ! bOsVersionInfoEx ) return 1;

   // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

   pGNSI = (PGNSI) GetProcAddress(
      GetModuleHandle(TEXT("kernel32.dll")), 
      "GetNativeSystemInfo");
   if(NULL != pGNSI)
      pGNSI(&si);
   else GetSystemInfo(&si);

   if ( VER\_PLATFORM\_WIN32\_NT==osvi.dwPlatformId && 
        osvi.dwMajorVersion > 4 )
   {
      StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));

      // Test for the specific product.

      if ( osvi.dwMajorVersion == 6 )
      {
         if( osvi.dwMinorVersion == 0 )
         {
            if( osvi.wProductType == VER\_NT\_WORKSTATION )
                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
            else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
         }

         if ( osvi.dwMinorVersion == 1 || osvi.dwMinorVersion == 2 )
         {
            if ( osvi.wProductType == VER\_NT\_WORKSTATION && osvi.dwMinorVersion == 1)
                StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
            else
            if ( osvi.wProductType == VER\_NT\_WORKSTATION && osvi.dwMinorVersion == 2)
                StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8 "));
            else 
                StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
         }

         pGPI = (PGPI) GetProcAddress(
            GetModuleHandle(TEXT("kernel32.dll")), 
            "GetProductInfo");

         pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);

         switch( dwType )
         {
            case PRODUCT\_ULTIMATE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
               break;
            case PRODUCT\_PROFESSIONAL:
               StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
               break;
            case PRODUCT\_HOME\_PREMIUM:
               StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
               break;
            case PRODUCT\_HOME\_BASIC:
               StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
               break;
            case PRODUCT\_ENTERPRISE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
               break;
            case PRODUCT\_BUSINESS:
               StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
               break;
            case PRODUCT\_STARTER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
               break;
            case PRODUCT\_CLUSTER\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
               break;
            case PRODUCT\_DATACENTER\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
               break;
            case PRODUCT\_DATACENTER\_SERVER\_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
               break;
            case PRODUCT\_ENTERPRISE\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
               break;
            case PRODUCT\_ENTERPRISE\_SERVER\_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
               break;
            case PRODUCT\_ENTERPRISE\_SERVER\_IA64:
               StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
               break;
            case PRODUCT\_SMALLBUSINESS\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
               break;
            case PRODUCT\_SMALLBUSINESS\_SERVER\_PREMIUM:
               StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
               break;
            case PRODUCT\_STANDARD\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
               break;
            case PRODUCT\_STANDARD\_SERVER\_CORE:
               StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
               break;
            case PRODUCT\_WEB\_SERVER:
               StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
               break;
         }
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
      {
         if( GetSystemMetrics(SM\_SERVERR2) )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
         else if ( osvi.wSuiteMask & VER\_SUITE\_STORAGE\_SERVER )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
         else if ( osvi.wSuiteMask & VER\_SUITE\_WH\_SERVER )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
         else if( osvi.wProductType == VER\_NT\_WORKSTATION &&
                  si.wProcessorArchitecture==PROCESSOR\_ARCHITECTURE\_AMD64)
         {
            StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
         }
         else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));

         // Test for the server type.
         if ( osvi.wProductType != VER\_NT\_WORKSTATION )
         {
            if ( si.wProcessorArchitecture==PROCESSOR\_ARCHITECTURE\_IA64 )
            {
                if( osvi.wSuiteMask & VER\_SUITE\_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
                else if( osvi.wSuiteMask & VER\_SUITE\_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
            }

            else if ( si.wProcessorArchitecture==PROCESSOR\_ARCHITECTURE\_AMD64 )
            {
                if( osvi.wSuiteMask & VER\_SUITE\_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
                else if( osvi.wSuiteMask & VER\_SUITE\_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
                else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
            }

            else
            {
                if ( osvi.wSuiteMask & VER\_SUITE\_COMPUTE\_SERVER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
                else if( osvi.wSuiteMask & VER\_SUITE\_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
                else if( osvi.wSuiteMask & VER\_SUITE\_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
                else if ( osvi.wSuiteMask & VER\_SUITE\_BLADE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
                else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
            }
         }
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
      {
         StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
         if( osvi.wSuiteMask & VER\_SUITE\_PERSONAL )
            StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
         else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
      }

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
      {
         StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));

         if ( osvi.wProductType == VER\_NT\_WORKSTATION )
         {
            StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
         }
         else 
         {
            if( osvi.wSuiteMask & VER\_SUITE\_DATACENTER )
               StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
            else if( osvi.wSuiteMask & VER\_SUITE\_ENTERPRISE )
               StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
            else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
         }
      }

       // Include service pack (if any) and build number.

      if( \_tcslen(osvi.szCSDVersion) > 0 )
      {
          StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
          StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
      }

      TCHAR buf[80];

      StringCchPrintf( buf, 80, TEXT(" (build \%d)"), osvi.dwBuildNumber);
      StringCchCat(pszOS, BUFSIZE, buf);

      if ( osvi.dwMajorVersion >= 6 )
      {
         if ( si.wProcessorArchitecture==PROCESSOR\_ARCHITECTURE\_AMD64 )
            StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
         else if (si.wProcessorArchitecture==PROCESSOR\_ARCHITECTURE\_INTEL )
            StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
      }

      return TRUE; 
   }

   else
   {  
      printf( "This sample does not support this version of Windows.
");
      return FALSE;
   }
}

int \_\_cdecl \_tmain()
{
    TCHAR szOS[BUFSIZE];

    if( GetOSDisplayString( szOS ) )
    {
        \_tprintf( TEXT("
\%s
"), szOS );
        cin.get();
    }
}


Dette returnerer Microsoft Windows 8 (build 8102), 64-bit på min Windows 8 Test Machine

Andre referencer 1


En anden mulighed ved brug af WMI-klassen Win32\_OperatingSystem [12]


#include "stdafx.h"
#define \_WIN32\_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")

#pragma argsused
int main(int argc, char* argv[])
{
    BSTR strNetworkResource;
    //To use a WMI remote connection set localconn to false and configure the values of the pszName, pszPwd and the name of the remote machine in strNetworkResource    
    strNetworkResource = L"\\.\root\CIMV2";

    COAUTHIDENTITY *userAcct =  NULL ;
    COAUTHIDENTITY authIdent;

    // Initialize COM. ------------------------------------------

    HRESULT hres;
    hres =  CoInitializeEx(0, COINIT\_MULTITHREADED);
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
        cout << \_com\_error(hres).ErrorMessage() << endl;
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                  // Program has failed.
    }

    // Set general COM security levels --------------------------


        hres =  CoInitializeSecurity(
            NULL,
            -1,                          // COM authentication
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC\_C\_AUTHN\_LEVEL\_DEFAULT,   // Default authentication
            RPC\_C\_IMP\_LEVEL\_IMPERSONATE, // Default Impersonation
            NULL,                        // Authentication info
            EOAC\_NONE,                   // Additional capabilities
            NULL                         // Reserved
            );


    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl;
        cout << \_com\_error(hres).ErrorMessage() << endl;
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                    // Program has failed.
    }

    // Obtain the initial locator to WMI -------------------------

    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(CLSID\_WbemLocator, 0, CLSCTX\_INPROC\_SERVER, IID\_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl;
        cout << \_com\_error(hres).ErrorMessage() << endl;
        CoUninitialize();       
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;                 // Program has failed.
    }

    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;

        hres = pLoc->ConnectServer(
             \_bstr\_t(strNetworkResource),      // Object path of WMI namespace
             NULL,                    // User name. NULL = current user
             NULL,                    // User password. NULL = current
             0,                       // Locale. NULL indicates current
             NULL,                    // Security flags.
             0,                       // Authority (e.g. Kerberos)
             0,                       // Context object
             &pSvc                    // pointer to IWbemServices proxy
             );


    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" << hex << hres << endl;    
        cout << \_com\_error(hres).ErrorMessage() << endl;
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();          
        return 1;                // Program has failed.
    }

    cout << "Connected to root\CIMV2 WMI namespace" << endl;

    // Set security levels on the proxy -------------------------

        hres = CoSetProxyBlanket(
           pSvc,                        // Indicates the proxy to set
           RPC\_C\_AUTHN\_WINNT,           // RPC\_C\_AUTHN\_xxx
           RPC\_C\_AUTHZ\_NONE,            // RPC\_C\_AUTHZ\_xxx
           NULL,                        // Server principal name
           RPC\_C\_AUTHN\_LEVEL\_CALL,      // RPC\_C\_AUTHN\_LEVEL\_xxx
           RPC\_C\_IMP\_LEVEL\_IMPERSONATE, // RPC\_C\_IMP\_LEVEL\_xxx
           NULL,                        // client identity
           EOAC\_NONE                    // proxy capabilities
        );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
        cout << \_com\_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }

    // Use the IWbemServices pointer to make requests of WMI ----

    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery( L"WQL", L"SELECT * FROM Win32\_OperatingSystem",
    WBEM\_FLAG\_FORWARD\_ONLY | WBEM\_FLAG\_RETURN\_IMMEDIATELY, NULL, &pEnumerator);

    if (FAILED(hres))
    {
        cout << "ExecQuery failed" << " Error code = 0x"    << hex << hres << endl;
        cout << \_com\_error(hres).ErrorMessage() << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        cout << "press enter to exit" << endl;
        cin.get();      
        return 1;               // Program has failed.
    }



    // Get the data from the WQL sentence
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;

    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM\_INFINITE, 1, &pclsObj, &uReturn);

        if(0 == uReturn || FAILED(hr))
          break;

        VARIANT vtProp;

                hr = pclsObj->Get(L"Caption", 0, &vtProp, 0, 0);// String
                if (!FAILED(hr))
                {
                    wcout << "OS Version " << vtProp.bstrVal << endl;
                }

                hr = pclsObj->Get(L"BuildNumber", 0, &vtProp, 0, 0);// String
                if (!FAILED(hr))
                {
                    wcout << "Build Number " << vtProp.bstrVal << endl;
                }

                hr = pclsObj->Get(L"Version", 0, &vtProp, 0, 0);// String
                if (!FAILED(hr))
                {
                    wcout << "Version " << vtProp.bstrVal << endl;
                }

                VariantClear(&vtProp);


        pclsObj->Release();
        pclsObj=NULL;
    }

    // Cleanup

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    if (pclsObj!=NULL)
     pclsObj->Release();

    CoUninitialize();
    cout << "press enter to exit" << endl;
    cin.get();
    return 0;   // Program successfully completed.
}


Denne kode returnerer



  OS Version Microsoft Windows Developer Preview Bygningsnummer 8102
  Version 6.2.8102



På Windows 8 udvikler preview version.

Andre referencer 2


OK, jeg håbede, at nogen allerede har gjort dette ... men det gætter jeg ikke, så her går du:


Windows 8 Forbruger Forhåndsvisning


//OSVERSIONINFO for GetVersionEx returns:
dwMajorVersion = 6;
dwMinorVersion = 2;
wProductType = 1;

//GetProductInfo returns:
dwType = 0x4A;   //Not documented yet???


PS. Jeg har ikke VS IDE installeret der. Måtte lave en lille app for at få dem ...

Andre referencer 3


Windows 8 er 6.2.

Windows Server 2012 er også 6.2.

Se: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724834(v=vs.85).aspx[13]

Andre referencer 4


En anden mulig metode til grundlæggende (større, mindre) validering af systemet, men ikke dybtgående produktdetaljer, er at kontrollere versionen af ​​en kernesystemfil, f.eks. Kernel32.dll.


Credits til en anden tråd til brug på GetFileVersionEx ...


Undskyld for sen bump ..;)


#include <Windows.h>
#include <stdio.h>
#include "Shlwapi.h"

#define a64 "(x64)"
#define i86 "(x86)"

#pragma comment( lib, "Shlwapi.lib")
#pragma comment( lib, "Version.lib")

BOOL IsWow64();
void PrintSystemVersion();

int main()
{
    PrintSystemVersion();

    getchar();
}

void PrintSystemVersion()
{
    DWORD dwSize = 0;
    BYTE *pbVersionInfo = NULL;
    VS\_FIXEDFILEINFO *pFileInfo = NULL;
    UINT puLenFileInfo = 0;
    TCHAR pszPath[ MAX\_PATH ];
    DWORD dwMajor, dwMinor;
    BOOL Is64 = FALSE;

    GetSystemDirectory( pszPath, sizeof( pszPath ) );

    PathAppend(pszPath, "kernel32.dll");

    dwSize = GetFileVersionInfoSize(pszPath, NULL);

    if (dwSize != 0)
    {
        pbVersionInfo = new BYTE[dwSize];

        if (GetFileVersionInfo(pszPath, 0, dwSize, pbVersionInfo))
        {
            if (VerQueryValue(pbVersionInfo, "\", (LPVOID*)&pFileInfo, &puLenFileInfo))
            {
                if ( IsWow64( ) == TRUE ) {
                    Is64 = TRUE;
                    dwMajor = pFileInfo->dwProductVersionMS >> 16 & 0xff; 
                    dwMinor = pFileInfo->dwProductVersionMS >> 0 & 0xff;
                } else {
                    dwMajor = pFileInfo->dwProductVersionMS;
                    dwMinor = pFileInfo->dwProductVersionMS;
                }
                if ( dwMajor == 5 )
                {
                    if ( dwMinor ==  0 ) {
                        printf("Windows 2000 \%s
", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 1) {
                        printf("Windows XP \%s
", Is64 ? a64 : i86);
                    }
                }
                else if ( dwMajor == 6)
                {
                    if ( dwMinor == 0) {
                        printf("Windows Vista \%s
", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 1) {
                        printf("Windows 7 \%s
", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 2) {
                        printf("Windows 8 \%s
", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 3) {
                        printf("Windows 8.1 \%s
", Is64 ? a64 : i86);
                    }
                }
            }
        }
    }
}

BOOL IsWow64()
{
    typedef BOOL(WINAPI *LPFN\_ISWOW64PROCESS) (HANDLE, PBOOL);
    LPFN\_ISWOW64PROCESS fnIsWow64Process;

    BOOL bIsWow64 = FALSE;

    fnIsWow64Process = (LPFN\_ISWOW64PROCESS)GetProcAddress(
        GetModuleHandle(TEXT("kernel32")), "IsWow64Process");

    if (NULL != fnIsWow64Process)
    {
        if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
        {
            bIsWow64 = TRUE;
        }
    }
    return bIsWow64;
}

Andre referencer 5


Ifølge denne MSDN-side anbefales det faktisk at bruge funktionen Version Helper i stedet for GetVersionInfoEx for at bestemme den kørende Windows-version. Som beskrevet på siden GetVersionEx, kan denne API forsvinde fremover. [14] [15]