22 out of 37 rated this helpful - Rate this topic

Example: Getting WMI Data from the Local Computer

You can use the procedure and code examples in this topic to create a complete WMI client application that performs COM initialization, connects to WMI on the local computer, retrieves data semisynchronously, and then cleans up. This example gets the name of the operating system on the local computer and displays it. To retrieve data from a remote computer, see Example: Getting WMI Data from a Remote Computer. For getting the data asynchronously, see Example: Getting WMI Data from the Local Computer Asynchronously.

The following procedure is used to execute the WMI application. Steps 1 through 5 contain all the steps required to set up and connect to WMI, and steps 6 and 7 are where data is queried and received.

  1. Initialize COM parameters with a call to CoInitializeEx.

    For more information, see Initializing COM for a WMI Application.

  2. Initialize COM process security by calling CoInitializeSecurity.
    Windows 2000:  Specify the default authentication credentials for a user by using a SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter of CoInitializeSecurity.

    For more information, see Setting the Default Process Security Level Using C++.

  3. Obtain the initial locator to WMI by calling CoCreateInstance.

    For more information, see Creating a Connection to a WMI Namespace.

  4. Obtain a pointer to IWbemServices for the root\cimv2 namespace on the local computer by calling IWbemLocator::ConnectServer. To connect to a remote computer, see Example: Getting WMI Data from a Remote Computer.

    For more information, see Creating a Connection to a WMI Namespace.

  5. Set IWbemServices proxy security so the WMI service can impersonate the client by calling CoSetProxyBlanket.

    For more information, see Setting the Security Levels on a WMI Connection.

  6. Use the IWbemServices pointer to make requests of WMI. This example executes a query for the name of the operating system by calling IWbemServices::ExecQuery.

    The following WQL query is one of the method arguments.

    SELECT * FROM Win32_OperatingSystem

    The result of this query is stored in an IEnumWbemClassObject pointer. This allows the data objects from the query to be retrieved semisynchronously with the IEnumWbemClassObject interface. For more information, see Enumerating WMI. For getting the data asynchronously, see Example: Getting WMI Data from the Local Computer Asynchronously.

    For more information about making requests to WMI, see Manipulating Class and Instance Information, Querying WMI, and Calling a Method.

  7. Get and display the data from the WQL query. The IEnumWbemClassObject pointer is linked to the data objects that the query returned, and the data objects can be retrieved with the IEnumWbemClassObject::Next method. This method links the data objects to an IWbemClassObject pointer that is passed into the method. Use the IWbemClassObject::Get method to get the desired information from the data objects.

    The following code example is used to get the Name property from the data object, which provides the name of the operating system.

    
    VARIANT vtProp;
    
    // Get the value of the Name property
    hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
    
    

    After the value of the Name property is stored in the VARIANT variable vtProp, it can then be displayed to the user.

    For more information, see Enumerating WMI.

The following code example retrieves WMI data semisynchronously from a local computer.


#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

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

int main(int argc, char **argv)
{
    HRESULT hres;

    // Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
            << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    // Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------

    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;
        CoUninitialize();
        return 1;                    // Program has failed.
    }
    
    // Step 3: ---------------------------------------------------
    // 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;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    // Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method

    IWbemServices *pSvc = NULL;
	
    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOT\\CIMV2"), // 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;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

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


    // Step 5: --------------------------------------------------
    // 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;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----

    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t("SELECT * FROM Win32_OperatingSystem"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    if (FAILED(hres))
    {
        cout << "Query for operating system name failed."
            << " Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    // Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
 
    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;
   
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;

        // Get the value of the Name property
        hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
        wcout << " OS Name : " << vtProp.bstrVal << endl;
        VariantClear(&vtProp);

        pclsObj->Release();
    }

    // Cleanup
    // ========
    
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    pclsObj->Release();
    CoUninitialize();

    return 0;   // Program successfully completed.
	
}

 

 

Send comments about this topic to Microsoft

Build date: 3/9/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Getting csproduct info
How can I retrieve in a C++ program the info returned by "wmic csproduct" on the command line. Cannot find the Win32 class corresponding to the csproduc alias.
Getting Error in BORLAND C++ 6
I don`t have wbemuuid.lib alongwith Borland C++ 6 compiler. I want to access hardware parameters (like fan speed, CPU temperature) through WMI &amp; having restriction to do with Borland 6 only.

Pls provide some solution. How can I proceed further to run one sample atleast !


[tfl - 01 04 12] Hi - and thanks for your post. Community content is not the appropriate place for technical support queries. Instead, you should visit the MSDN Forums at http://forums.microsoft.com/MSDN, where such posts are welcomed and where you stand a much better chance of getting your query resolved. Sorry if that's not the answer you wanted to hear.

How to fetch WMI Object Data Value
This works fine whenever I am querying for data that are of simple data types (int, long, string etc). What do I do if the value is a class instance?? Any examples that can help me out here.
Sample code omitted linking comsuppw.lib
link lib on Project setting tab or,
add #pragma comment(lib, "comsuppw.lib") line
VC6
I got this to work just fine on Visual Studio 6, with the Platfrom SDK Feb 2003 and DDK version 7600.16385 installed.

However, wbemuuid.lib from that DDK is incompatible with VC6 (it was compiled with a later version of the compiler), so you can't link to it. Instead, you can do the following:

1. Add #define INITGUID to the top of the file
2. Replace the #pragma comment(lib, "wbemuuid.lib") line with the following (these values were derived from comments in the wbemidl.h file):

DEFINE_GUID(CLSID_WbemLocator, 0x4590f811, 0x1d3a, 0x11d0, 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24);
DEFINE_GUID(IID_IWbemLocator,  0xdc12a687, 0x737f, 0x11cf, 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24);


Obviously, the line pclsObj->Release() near the end of the file is a bug and needs to be removed, but there is no need to add libraries to the project and I also didn't need to move the "using namespace std" elsewhere. I also didn't see the internal compiler error someone mentioned.

By the way, the "while (pEnumerator)" line is misleading: it implies that pEnumerator would become zero during the loop but in fact it never changes. It would have been clearer if the code would say: "if (pEnumerator) for( ; ; )".

===Jac
Mistake in example
I believe the final "pEnumerator->Release();" in the Cleanup section is not required.
Bug fix bugged...
if you're going to fix a bug please take out the faulty code. You left in the old pclsObj->Release(); which throws an unhanded exception. Remove the one below at "cleanup"
Mistake in code
$0Double call of this function causes crash to the program.$0 $0    pclsObj->Release();$0 $0$0 $0
Need to update VC++ to later version
The above code works in VC++ 8 or later versions. It may also work in VC++ 7 but I did not check for this version.
If you want to build it in VC++ 6.0 you need to move the "usingnamespace std" line right before main function
and add needed libraries to work. I guess it will be easier to just install later versions of VC++ then to do
that extra work.

Example:

#define

_WIN32_DCOM

#include

<iostream>

#include

<comdef.h>

#include

<Wbemidl.h>


#pragma

comment(lib, "wbemuuid.lib")


using

namespace std;

int

main(int argc, char **argv)

{

HRESULT hres;
.
.
.

Memory leak
The above example contains a memory leak: the statement "pclsObj->Release();" should be at the end of the body of the while loop instead of after the while loop.

Update (09/09): looks like they added the Release() to the loop, but left the one after the loop so the code now crashes with a double Release()
I Can't compile this sample code by VC++6
I try to compile this sample code by VC++6, I got an error message like this:
Compiling...
WMUTIL.CPP
c:\program files\microsoft visual studio\vc98\include\comutil.h(101) : fatal error C1001: INTERNAL COMPILER ERROR