GetVersionEx under Windows 8

GetVersionEx under Windows 8

本文关键字:Windows under GetVersionEx      更新时间:2023-10-16

我正在编写一个C++代码来确定它在什么操作系统上运行。我使用GetVersionEx() API来完成这项工作,这段代码作为教程,但它似乎无法处理Windows 8。有人知道如何修复它以在Windows8下运行吗?

根据MSDN论坛和本文中的几条评论,Windows 8的版本号是6.2

这是在Windows8开发者预览版中更新和测试的示例代码

#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.n");
      return FALSE;
   }
}
int __cdecl _tmain()
{
    TCHAR szOS[BUFSIZE];
    if( GetOSDisplayString( szOS ) )
    {
        _tprintf( TEXT("n%sn"), szOS );
        cin.get();
    }
}

这将在我的Windows 8测试机上返回Microsoft Windows 8 (build 8102), 64-bit

使用Win32_OperatingSystem WMI类的另一个选项

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

此代码返回

操作系统版本Microsoft Windows开发者预览版内部版本号8102版本6.2.8102

在Windows 8开发人员预览版上。

好吧,我希望有人已经这么做了。。。但是,我想不会,所以给你:

Windows 8消费者预览版

//OSVERSIONINFO for GetVersionEx returns:
dwMajorVersion = 6;
dwMinorVersion = 2;
wProductType = 1;
//GetProductInfo returns:
dwType = 0x4A;   //Not documented yet???

PS。我没有在那里安装VS IDE。必须制作一个小应用程序才能获得这些。。。

Windows 8版本为6.2。
Windows Server 2012也是6.2版本。
请参阅:http://msdn.microsoft.com/en-us/library/windows/desktop/ms724834(v=vs.85).aspx

对系统进行基本(主要、次要)验证但不深入产品详细信息的另一种可能方法是检查核心系统文件的版本,例如kernel32.dll。

在GetFileVersionEx上使用的另一个线程的信用。。。

抱歉迟到了..;)

#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 %srn", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 1) {
                        printf("Windows XP %srn", Is64 ? a64 : i86);
                    }
                }
                else if ( dwMajor == 6)
                {
                    if ( dwMinor == 0) {
                        printf("Windows Vista %srn", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 1) {
                        printf("Windows 7 %srn", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 2) {
                        printf("Windows 8 %srn", Is64 ? a64 : i86);
                    }
                    else if ( dwMinor == 3) {
                        printf("Windows 8.1 %srn", 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;
}

根据这个MSDN页面,实际上建议使用Version Helper函数而不是GetVersionInfoEx来确定运行的Windows版本。如GetVersionEx页所述,API可能在未来消失。