Sto scrivendo un codice C++ per determinare quale sistema operativo è in esecuzione. Io uso l'API GetVersionEx()
per farlo e this code come tutorial, ma non sembra gestire Windows 8. Qualcuno sa come risolverlo per l'esecuzione in Windows 8?GetVersionEx in Windows 8
risposta
Secondo alcuni commenti nei forum MSDN e this article il numero di versione per Windows 8 è 6.2
Questo è il codice di esempio aggiornato e testato in 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.\n");
return FALSE;
}
}
int __cdecl _tmain()
{
TCHAR szOS[BUFSIZE];
if(GetOSDisplayString(szOS))
{
_tprintf(TEXT("\n%s\n"), szOS);
cin.get();
}
}
Ciò restituisce Microsoft Windows 8 (build 8102), 64-bit
su il mio Windows 8 Test Machine
OK. Questo è quello che ho ottenuto.Mi auguro che abbiano aggiornato tutto ciò che è presente in MSDN (inclusi i nomi delle licenze per Windows 8 ...) – ahmd0
OK, speravo che qualcuno lo avesse già fatto ... ma, suppongo di no, ecco qua:
Windows 8 Consumer Preview
//OSVERSIONINFO for GetVersionEx returns:
dwMajorVersion = 6;
dwMinorVersion = 2;
wProductType = 1;
//GetProductInfo returns:
dwType = 0x4A; //Not documented yet???
PS. Non ho installato VS IDE lì. Ha dovuto fare una piccola applicazione per ottenere quelle ...
0x4A corrisponde a PRODUCT_PRERELEASE (utilizzato nelle versioni di anteprima per sviluppatori e consumer). –
Si noti che con Windows 8.1/10, a meno che l'app non abbia un manifest incorporato con il GUID supportato per Windows 8.1/10 in esso, '' GetVersionEx'' restituirà comunque 6.2. Vedi [Manifest Madness] (http://blogs.msdn.com/b/chuckw/archive/2013/09/10/manifest-madness.aspx) –
Un'altra opzione utilizzando la classe WMI Win32_OperatingSystem
#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.
}
Questo codice restituisce
versione del sistema operativo Microsoft Windows Developer Preview numero di build 8102 Version 6.2.8102
Su Windows 8 versione di anteprima per sviluppatori.
Questa è l'unica tecnica affidabile, che fornisce la versione corretta per tutti i futuri: versioni di Windows sconosciute, senza problemi di "Is-This-Feature-Available" o manifest. – Ajay
Windows 8 è 6.2.
Windows Server 2012 è anche 6.2.
See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724834(v=vs.85).aspx
Grazie per il collegamento alla documentazione MS con la tabella delle versioni di Windows. –
Secondo this MSDN page, è in realtà consiglia di utilizzare le funzioni di supporto versione invece di GetVersionInfoEx
per determinare la versione di Windows in esecuzione. Come descritto nella pagina GetVersionEx
, tale API potrebbe scomparire in futuro.
In effetti MS depracated 'GetVersionEx'. Ma perché usare versionHelper funziona senza problemi? L'API mi sembra abbastanza semplificata. –
Hai ragione. Ho guardato di nuovo e il codice è stato semplificato. – rubenvb
Un altro metodo possibile per la convalida di base (principale, minore) del sistema ma non in dettaglio sui dettagli del prodotto è di controllare la versione di un file di sistema di base, ad esempio kernel32.dll.
crediti verso un altro thread per l'utilizzo su GetFileVersionEx ...
Ci scusiamo per il ritardo urto ..;)
#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\r\n", Is64 ? a64 : i86);
}
else if (dwMinor == 1) {
printf("Windows XP %s\r\n", Is64 ? a64 : i86);
}
}
else if (dwMajor == 6)
{
if (dwMinor == 0) {
printf("Windows Vista %s\r\n", Is64 ? a64 : i86);
}
else if (dwMinor == 1) {
printf("Windows 7 %s\r\n", Is64 ? a64 : i86);
}
else if (dwMinor == 2) {
printf("Windows 8 %s\r\n", Is64 ? a64 : i86);
}
else if (dwMinor == 3) {
printf("Windows 8.1 %s\r\n", 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;
}
Il codice va bene, hai solo bisogno di trovare il numero di versione per Windows 8. Come 6.1 è Windows 7, forse è 6.2 per 8. Sapendo questo, è possibile regolare il codice in base alla documentazione MS per 8. –
Considerando le differenze piuttosto enormi in Windows 8, direi che il numero di versione sarebbe 7.0. Forse anche 8,0 se vogliono essere sani di mente e saltare un numero di versione. – cHao
Qualche idea su quali versioni di Windows 8 avrà MS? – ahmd0