How to: Query for Specific Instances of a Class (C/C++)

This topic provides step-by-step instructions for querying instances of a class with WQL (WMI Query Language) using the Windows Management Infrastructure (MI) native API. In addition to the steps, a full source code example is provided at the end of the topic..

Note

To see the MI .NET API and Microsoft Visual C# version of this topic, refer to How to: Query for Specific Instances of a Class (C)

 

Step-by-step Instructions

  1. Insert an include directive for the MI header file. (This file ships as part of the Windows Software Development Kit (SDK) for Windows 8.)

    #include <mi.h>
    
  2. Add the MI import library (mi.lib) to the project's linker dependencies. (This file ships as part of the Windows Software Development Kit (SDK) for Windows 8.)

  3. Initialize the application via MI_Application_Initialize. It is recommended to have only one MI_Application per process. The MI_Application returned from this function should always be closed, or de-initialized, via MI_Application_Close.

    MI_RESULT miResult = MI_Application_Initialize(0,               // Flags - Must be 0
                                                   NULL,            // Application ID
                                                   NULL,            // Extended error
                                                   &amp;miApplication); // Application 
    if (miResult != MI_RESULT_OK)
    { /* Handle error */ }
    
  4. Create an MI session against the specified destination (computer) with the specified protocol (WinRM, in this example) via MI_Application_NewSession. The session must be closed via MI_Session_Close.

    MI_RESULT miResult = MI_Application_NewSession(&amp;miApplication, // Application 
                                                   L"WINRM",       // WimRM Protocol
                                                   L"localhost",   // Machine destination
                                                   NULL,           // Options
                                                   NULL,           // Callbacks
                                                   NULL,           // Extended error
                                                   &amp;miSession);    // Session 
    if (miResult != MI_RESULT_OK)
    { /* Handle error */ }
    
  5. Enumerate the instances of the desired class via MI_Session_QueryInstances passing the desired CIM namespace and WQL to use. The following snippet will return two instances representing two standard Windows processes where the handle property (representing a process ID, or PID) has a value of either 0 or 4.

    MI_Operation miOperation = MI_OPERATION_NULL;
    
    MI_Session_QueryInstances(miSession,      // Session 
                              0,              // Flags
                              NULL,           // Options
                              namespaceName,  // CIM Namespace
                              L"WQL",         // Query dialect
                              L"select * from win32_process where handle = 0 or handle = 4",
                              NULL,           // Callbacks
                              &amp;miOperation);  // Operation
    
  6. The MI_Session_QueryInstances function (called in the previous step) returns an MI_Operation. To retrieve the enumerated instances from that struct, you must call MI_Operation_GetInstance in a loop until it returns a moreResults value of MI_FALSE. For each instances that is returned via MI_Operation_GetInstance, MI_Instance_GetElement is called to retrieve the desired property. The following code uses a simple do/while loop and outputs the Name property for all instances of the Win32_Process class (representing all running processes).

    MI_Result miResult = MI_RESULT_OK;
    MI_Boolean moreResults;
    const MI_Char* errorString = NULL;
    MI_Uint32 instanceCount = 0;
    MI_Instance *miInstance;
    const MI_Instance* errorDetails = NULL;
    
    do {    
        miResult = MI_Operation_GetInstance(&amp;miOperation,                     // Operation
                                            (const MI_Instance**)&amp;miInstance, // Instance
                                            &amp;moreResults,                     // More results? 
                                            &amp;miResult,                        // Result
                                            &amp;errorString,                     // Error message
                                            &amp;errorDetails);                   // Completion details
        if (miResult != MI_RESULT_OK) {
            wprintf(L"MI_Operation_GetInstance failed. MI_RESULT: %ld\n", miResult);
            break;
        }
    
        if (miInstance) {
            MI_Value value;
            MI_Type type;   
            MI_Uint32 flags;
    
            miResult = MI_Instance_GetElement(miInstance,  // Instance
                                              L"Name",     // Element (property) name
                                              &amp;value,      // Element value
                                              &amp;type,       // Element type
                                              &amp;flags,      // Flags
                                              NULL);       // Index
            if (miResult != MI_RESULT_OK) {
               wprintf(L"MI_Instance_GetElement failed. MI_RESULT: %ld)\n", miResult);
               return;
            }
    
            wprintf(L"Process Name: %s\n", value.string);
    
            instanceCount++;
        }
    
    } while (miResult == MI_RESULT_OK &amp;&amp; moreResults == MI_TRUE);
    
  7. Close the operation via MI_Operation_Close. All operations must be closed. If an operation is not closed, MI_Session_Close will block until all of its operations are closed. Also note that MI_Operation_Close will cancel an operation if it is still running. However, results must be consumed before MI_Operation_Close can complete. For synchronous operations (such as the example in this topic), MI_Operation_Close is blocked until the final result has been consumed (i.e., until the moreResults output parameters is set to MI_FALSE).

    miResult = MI_Operation_Close(&amp;miOperation);
    if (miResult != MI_RESULT_OK)
    { /* Handle error */ }
    
  8. Close the MI session via MI_Session_Close. If this function fails (reflected in the MI_Result return code), it is likely due to an invalid parameter, out of memory errors, or access denied. Invalid parameter means a programming error happened. When an out of memory error happens, the session will shut down as best it can. Access denied means the security context while calling the MI_Session_Close function is different than the one used when the session was created. This could happen if closing from a different thread and neglecting to impersonate.

    MI_RESULT miResult = MI_Session_Close(&amp;miSession, // Session
                                          NULL,       // Completion context
                                          NULL);      // Completion callback
    if (miResult != MI_RESULT_OK)
    { /* Handle error */ }
    
  9. The last MI call that should be made is a call to MI_Application_Close. Note that this call will block until all operations and sessions are fully closed.

    MI_RESULT miResult = MI_Application_Close(&amp;miApplication);
    if (miResult != MI_RESULT_OK)
    { /* Handle error */ }
    

Example

The following code sample enumerates all instances of the Win32_Process class (which represents active processes) on the local machine, and prints the name of each process.

Note

In a real application you would define as parameters the computer name ("localhost"), CIM namespace ("root\cimv2"), and class name ("Win32_Process"). For purposes of demonstration, these have been hardcoded in this example. The Name property has also been hardcoded while printing.

 

#include "stdafx.h"
#include <mi.h>

void QueryInstances(MI_Session* miSession, 
                    _In_z_ const wchar_t* namespaceName, 
                    const wchar_t* className)
{
    MI_Operation miOperation = MI_OPERATION_NULL;

    MI_Session_QueryInstances(miSession,      // Session 
                              0,              // Flags
                              NULL,           // Options
                              namespaceName,  // CIM Namespace
                              L"WQL",         // Query dialect
                              L"select * from win32_process where handle = 0 or handle = 4",
                              NULL,           // Callbacks
                              &amp;miOperation);  // Operation
    MI_Result miResult = MI_RESULT_OK;
    MI_Boolean moreResults;
    const MI_Char* errorString = NULL;
    MI_Uint32 instanceCount = 0;
    MI_Instance *miInstance;
    const MI_Instance* errorDetails = NULL;

    do
    {
        miResult = MI_Operation_GetInstance(&amp;miOperation,                     // Operation 
                                            (const MI_Instance**)&amp;miInstance, // Instance
                                            &amp;moreResults,                     // More results?
                                            &amp;miResult,                        // Result
                                            &amp;errorString,                     // Error message
                                            &amp;errorDetails);                   // Completion details
        if (miResult != MI_RESULT_OK)
        {
            wprintf(L"MI_Operation_GetInstance failed. MI_RESULT: %ld\n", miResult);
            break;
        }
        if (miInstance)
        {
            MI_Value value;
            MI_Type type;
            MI_Uint32 flags;

            miResult = MI_Instance_GetElement(miInstance,  // Instance
                                              L"Name",     // Element (property) name
                                              &amp;value,      // Element value
                                              &amp;type,       // Element type
                                              &amp;flags,      // Flags
                                              NULL);       // Index
            if (miResult != MI_RESULT_OK)
            {
                wprintf(L"MI_Instance_GetElement failed. MI_RESULT: %ld)\n", miResult);
                return;
            }
            wprintf(L"Process Name: %s\n", value.string);

            instanceCount++;
        }

    } while (miResult == MI_RESULT_OK &amp;&amp; moreResults == MI_TRUE);

    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"Operation failed: MI_Result=%ld, errorString=%s\n", 
                miResult, errorString);
    }
    else
    {
        wprintf(L"Operation succeeded. Number of instances = %u\n", instanceCount);
    }

    miResult = MI_Operation_Close(&amp;miOperation);
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Operation_Close failed. MI_RESULT: %ld\n", miResult);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    MI_Result miResult = MI_RESULT_OK;
    MI_Application miApplication = MI_APPLICATION_NULL;
    MI_Session miSession = MI_SESSION_NULL;
    MI_Operation miOperation = MI_OPERATION_NULL;

    miResult = MI_Application_Initialize(0,                   // Flags - Must be 0
                                         NULL,                // Application ID
                                         NULL,                // Extended error
                                         &amp;miApplication);     // Application
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Application_Initialize failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }

    miResult = MI_Application_NewSession(&amp;miApplication, // Application 
                                         L"WINRM",       // WimRM Protocol
                                         L"localhost",   // Machine destination
                                         NULL,           // Options
                                         NULL,           // Callbacks
                                         NULL,           // Extended error
                                         &amp;miSession);    // Session 
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Application_NewSession failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }

    QueryInstances(&amp;miSession, L"root\\cimv2", L"Win32_Process");    

    miResult = MI_Session_Close(&amp;miSession, NULL, NULL);
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Session_Close failed. MI_Result: %ld\n", miResult);
        return -1;
    }

    miResult = MI_Application_Close(&amp;miApplication);
    if (miResult != MI_RESULT_OK) 
    {
        wprintf(L"MI_Application_Close failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }

    return 0;
}