This topic provides step-by-step instructions for enumerating the instances of a specified CIM class 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: Enumerate All Instances of a Class (C)
Step-by-step Instructions
- 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>
- 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.) 
- 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 &miApplication); // Application if (miResult != MI_RESULT_OK) { /* Handle error */ }
- 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(&miApplication, // Application L"WINRM", // WimRM Protocol L"localhost", // Machine destination NULL, // Options NULL, // Callbacks NULL, // Extended error &miSession); // Session if (miResult != MI_RESULT_OK) { /* Handle error */ }
- Enumerate the instances of the desired class via MI_Session_EnumerateInstances. In the following example, the code has hardcoded values for both the namespaceName and the className parameters. - MI_Operation miOperation = MI_OPERATION_NULL; MI_Session_EnumerateInstances(miSession, // Session 0, // Flags NULL, // Options "root\\cimv2", // CIM Namespace "Win32_Process", // Class name MI_FALSE, // Retrieve only keys NULL, // Callbacks &miOperation); // Operation
- The MI_Session_EnumerateInstances 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(&miOperation, // Operation (const MI_Instance**)&miInstance, // Instance &moreResults, // More results? &miResult, // Result &errorString, // Error message &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 &value, // Element value &type, // Element type &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 && moreResults == MI_TRUE);
- 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(&miOperation); if (miResult != MI_RESULT_OK) { /* Handle error */ }
- 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(&miSession, // Session NULL, // Completion context NULL); // Completion callback if (miResult != MI_RESULT_OK) { /* Handle error */ }
- 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(&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 simplicity, these have been hardcoded in this example.
#include "stdafx.h"
#include <mi.h>
void EnumerateAndPrintInstanceNames(MI_Session* miSession, 
                        _In_z_ const wchar_t* namespaceName, 
                        const wchar_t* className)
{
    MI_Operation miOperation = MI_OPERATION_NULL;
    MI_Session_EnumerateInstances(miSession,      // Session 
                                  0,              // Flags
                                  NULL,           // Options
                                  namespaceName,  // CIM Namespace
                                  className,      // Class name
                                  MI_FALSE,       // Retrieve only keys
                                  NULL,           // Callbacks
                                  &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
    {
        //Note that each instance becomes invalid after getting the next instance in the loop or
        //after closing the operation. Call the MI_Instance_Clone function to use an instance 
        //past this. Be sure to MI_Instance_Delete to close the cloned instance when finished.
        miResult = MI_Operation_GetInstance(&miOperation,                     // Operation 
                                            (const MI_Instance**)&miInstance, // Instance
                                            &moreResults,                     // More results?
                                            &miResult,                        // Result
                                            &errorString,                     // Error message
                                            &errorDetails);                   // Completion details
        if (miResult != MI_RESULT_OK)
        {
            wprintf(L"MI_Operation_GetInstance failed. MI_RESULT: %ld\n", miResult);
            break;
        }
        //The following demonstrates using the instance just received.
        if (miInstance)  
        {
            MI_Value value;
            MI_Type type;
            MI_Uint32 flags;
            //Athough the Name property is shown here to demonstrate, you could substitute another property
            miResult = MI_Instance_GetElement(miInstance,  // Instance
                                              L"Name",     // Element (property) name
                                              &value,      // Element value
                                              &type,       // Element type
                                              &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 && 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(&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
                                         &miApplication);     // Application
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Application_Initialize failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }
    miResult = MI_Application_NewSession(&miApplication, // Application 
                                         L"WINRM",       // WimRM Protocol
                                         L"localhost",   // Machine destination
                                         NULL,           // Options
                                         NULL,           // Callbacks
                                         NULL,           // Extended error
                                         &miSession);    // Session 
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Application_NewSession failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }
    EnumerateAndPrintInstanceNames(&miSession, L"root\\cimv2", L"Win32_Process");    
    miResult = MI_Session_Close(&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(&miApplication);
    if (miResult != MI_RESULT_OK) 
    {
        wprintf(L"MI_Application_Close failed. MI_RESULT: %ld\n", miResult);
        return -1;
    }
    return 0;
}