views:

217

answers:

3

Hi,

I recently saw this Stackoverflow question about detecting the "real" version of Windows.

I have a application that uses code thats only availible on Windows Vista and up. To maintain compatibility with Windows XP, I have created my own version which does exactly the same as the Vista code, but is nowhere near as fast as the Vista code. Currently the XP code is loaded when XP is detected from GetVersionEx(). However, obviously, when the application is run under XP compatability, this code is loaded unnecessarily. Now I know that I could check for the Vista method, but my code uses a lot of Vista-only code and I would rather not have to check if the method exists as I have already written XP checks and it would be easier just to change the one function.

Now my question: How can run this WMI query and return the result (the Windows version) as an int AND std::string: "Select Version from Win32_OperatingSystem"

I am using VC++ 2008.

A: 

Why you want to tell other parts of your program the OS is Vista-capable when it is running under XP compatibility? The OS emulate the XP as much as possible, changing its behavior according to version you specificed, not only for your code, but also for all the base service you are using, like Windows Shell, common control, base services like File IO, security, memory management, DLL loading, and whatever hacks that were introduced in Windows XP to make those ancient rushed-out games continue to work). Using Vista APIs under XP compatibility mode is asking for trouble.

Sheng Jiang 蒋晟
A: 

I don't use C++, but you can find samples here.

Uros Calakovic
A: 

Here's some code to get you the essential functionality: making the WMI query and retrieving the Version string.

Note that this sample doesn't bother with error checking -- and with all these COM calls, you'll need many lines of it. For examples see Uros' link, and also Example: Getting WMI Data from the Local Computer

#include <string>
#include <atlbase.h> // For ATL autorelease classes (CComBSTR, CComPtr)
#include <wbemidl.h> // For WMI
#pragma comment(lib, "wbemuuid.lib") // Link to WMI library. (Can do in library includes instead)

std::string GetOsVersionString()
{
    HRESULT hr = ::CoInitializeSecurity(NULL, -1, NULL, NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL, EOAC_NONE, NULL);

    CComPtr<IWbemLocator> pWbemLocator;
    hr = pWbemLocator.CoCreateInstance(CLSID_WbemLocator);

    CComPtr<IWbemServices> pWbemServices;
    hr = pWbemLocator->ConnectServer(CComBSTR(L"root\\cimv2"), NULL, NULL, 0, NULL, 0, NULL, &pWbemServices);

    CComPtr<IEnumWbemClassObject> pEnum;
    CComBSTR cbsQuery = L"Select Version from Win32_OperatingSystem";
    hr = pWbemServices->ExecQuery(CComBSTR("WQL"), cbsQuery, WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);

    ULONG uObjectCount = 0;
    CComPtr<IWbemClassObject> pWmiObject;
    hr = pEnum->Next(WBEM_INFINITE, 1, &pWmiObject, &uObjectCount);

    CComVariant cvtVersion;
    hr = pWmiObject->Get(L"Version", 0, &cvtVersion, 0, 0);

    std::string sOsVersion = CW2A(cvtVersion.bstrVal);
    return sOsVersion;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    std::string sOsVersion = GetOsVersionString();
    ::CoUninitialize();

    return 0;
}
Daryn