This topic provides step-by-step instructions for getting a specific (keyed) instance 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: Get a Specific Instance 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 */ }
- Create an MI_Instance that represents the class name and keys of the instance to be retrieved from the server via MI_Session_GetInstance. The following example function creates an instance with a hard-coded element (property) name of Handle and a value of 0. For the Win32_Process class (the class being used in this example), the Handle property is the process ID (PID) and the process with a PID of 0 is the System Idle Process. In a real-world scenario, you will want to specify the appropriate elements and values pursuant to the class you are attempting to obtain. - MI_Result CreateSearchInstance(MI_Session *miSession, _In_z_ const wchar_t *namespaceName, _In_z_ const wchar_t *className, MI_Boolean keysOnly, MI_Instance **inboundInstance) { MI_Result miResult; MI_Operation miOperation = MI_OPERATION_NULL; MI_Class *miClass = NULL; MI_Boolean moreResults; MI_Char *errorMessage = NULL; MI_Instance *completionDetails = NULL; MI_Instance *miInstance = NULL; *inboundInstance = NULL; MI_Session_GetClass(miSession, 0, NULL, namespaceName, className, NULL, &miOperation); MI_Operation_GetClass(&miOperation, (const MI_Class**)&miClass, &moreResults, &miResult, (const MI_Char**)&errorMessage, (const MI_Instance**)&completionDetails); if (miResult == MI_RESULT_OK) { MI_Application miApplication = MI_APPLICATION_NULL; miResult = MI_Session_GetApplication(miSession, &miApplication); if (miResult == MI_RESULT_OK) { miResult = MI_Application_NewInstanceFromClass(&miApplication, className, miClass, &miInstance); if (miResult == MI_RESULT_OK) { MI_Value miValue; miValue.string = L"0"; miResult = MI_Instance_SetElement(miInstance, L"Handle", &miValue, MI_STRING, 0); } } } // Cleanup in case of error if ((miResult != MI_RESULT_OK) && miInstance) { MI_Result _tmpResult = MI_Instance_Delete(miInstance); if (_tmpResult != MI_RESULT_OK) { wprintf(L"Failed to delete key instance. MI_Result: %ld\n", _tmpResult); } } { MI_Result _tmpResult = MI_Operation_Close(&miOperation); if (_tmpResult != MI_RESULT_OK) { wprintf(L"MI_Operation_Close failed. MI_Result: %ld\n", _tmpResult); } } if (miResult == MI_RESULT_OK) { *inboundInstance = miInstance; } return miResult; }
- Call MI_Session_GetInstance passing the key, or search, instance from the previous step. - Note - The following code uses a loop to enumerate the results of the MI_Session_GetInstance function. While not technically necessary for this particular example - as this example will always return one instance - it's included to illustrate how you would enumerate the results of a call to MI_Session_GetInstance that returns multiple instances. - void GetInstance(MI_Session* miSession, _In_z_ const wchar_t* namespaceName, const wchar_t* className, MI_Instance* searchInstance) { MI_Result miResult = MI_RESULT_OK; MI_Operation miOperation = MI_OPERATION_NULL; MI_Session_GetInstance(miSession, 0, NULL, namespaceName, searchInstance, NULL, &miOperation); MI_Instance *miInstance = NULL; MI_Boolean moreResults; MI_Char *errorMessage = NULL; MI_Instance *completionDetails = NULL; do { miResult = MI_Operation_GetInstance(&miOperation, (const MI_Instance**)&miInstance, &moreResults, &miResult, (const MI_Char**)&errorMessage, (const MI_Instance**)&completionDetails); if (miResult != MI_RESULT_OK) { wprintf(L"MI_Operation_GetInstance failed. MI_Result: %ld\n", miResult); } else { if (miResult != MI_RESULT_OK) { wprintf(L"Operation failed: MI_Result=%ld, errorString=%s, errorDetails=\n", miResult, errorMessage); } else 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); } else if (moreResults == MI_TRUE) { wprintf(L"More results are due and we have no instance, we will keep trying!\n"); } } } while (moreResults == MI_TRUE); miResult = MI_Operation_Close(&miOperation); if (miResult != MI_RESULT_OK) { wprintf(L"MI_Operation_Close failed. MI_Result: %ld\n", miResult); } }
- Delete key, or search, instance created earlier. - miResult = MI_Instance_Delete(searchInstance); if (miResult != MI_RESULT_OK) { /* Handle error */ }
- 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 attempts to get the instance of the Win32_Process class (which represents active processes) with a PID of 0 on the local machine, and if found, prints the name of 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>
MI_Result CreateSearchInstance(MI_Session *miSession, 
                               _In_z_ const wchar_t *namespaceName, 
                               _In_z_ const wchar_t *className, 
                               MI_Boolean keysOnly, 
                               MI_Instance **inboundInstance)
{
    MI_Result miResult;
    MI_Operation miOperation = MI_OPERATION_NULL;
    MI_Class *miClass = NULL;
    MI_Boolean moreResults;
    MI_Char *errorMessage = NULL;
    MI_Instance *completionDetails = NULL;
    MI_Instance *miInstance = NULL;
    *inboundInstance = NULL;
    MI_Session_GetClass(miSession, 0, NULL, namespaceName, className, NULL, &miOperation);
    MI_Operation_GetClass(&miOperation, 
                          (const MI_Class**)&miClass, 
                          &moreResults, 
                          &miResult, 
                          (const MI_Char**)&errorMessage, 
                          (const MI_Instance**)&completionDetails);
    if (miResult == MI_RESULT_OK)
    {
        MI_Application miApplication = MI_APPLICATION_NULL;
        miResult = MI_Session_GetApplication(miSession, &miApplication);
        if (miResult == MI_RESULT_OK)
        {
            miResult = MI_Application_NewInstanceFromClass(&miApplication, 
                                                           className, 
                                                           miClass, 
                                                           &miInstance);
            if (miResult == MI_RESULT_OK)
            {
                MI_Value miValue;
                miValue.string = L"0";
                miResult = MI_Instance_SetElement(miInstance, 
                                                  L"Handle", 
                                                  &miValue, 
                                                  MI_STRING, 
                                                  0);
            }
        }
    }
    // Cleanup in case of error
    if ((miResult != MI_RESULT_OK) && miInstance)
    {
        MI_Result _tmpResult = MI_Instance_Delete(miInstance);
        if (_tmpResult != MI_RESULT_OK)
        {
            wprintf(L"Failed to delete key instance. MI_Result: %ld\n", _tmpResult);
        }
    }
    {
        MI_Result _tmpResult = MI_Operation_Close(&miOperation);
        if (_tmpResult != MI_RESULT_OK)
        {
            wprintf(L"MI_Operation_Close failed. MI_Result: %ld\n", _tmpResult);
        }
    }
        
    if (miResult == MI_RESULT_OK)
    {
        *inboundInstance = miInstance;
    }
    return miResult;
}
void GetInstanceAndPrintProperty(MI_Session* miSession, 
                 _In_z_ const wchar_t* namespaceName, 
                 const wchar_t* className,
                 MI_Instance* searchInstance)
{
    MI_Result miResult = MI_RESULT_OK;
    MI_Operation miOperation = MI_OPERATION_NULL;
    MI_Session_GetInstance(miSession, 
                           0, 
                           NULL, 
                           namespaceName, 
                           searchInstance, 
                           NULL, 
                           &miOperation);
    MI_Instance *miInstance = NULL;
    MI_Boolean moreResults;
    MI_Char *errorMessage = NULL;
    MI_Instance *completionDetails = NULL;
    do
    {
        miResult = MI_Operation_GetInstance(&miOperation, 
                                            (const MI_Instance**)&miInstance, 
                                            &moreResults, 
                                            &miResult, 
                                            (const MI_Char**)&errorMessage, 
                                            (const MI_Instance**)&completionDetails);
            if (miResult != MI_RESULT_OK)
            {
                wprintf(L"Operation failed: MI_Result=%ld, errorString=%s, errorDetails=\n", 
                        miResult, errorMessage);
            }
            else 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);
            }
            else if (moreResults == MI_TRUE)
            {
                wprintf(L"More results are due and we have no instance, we will keep trying!\n");
            }
    } while (moreResults == MI_TRUE);
    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;
    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;
    }
    MI_Session miSession = MI_SESSION_NULL;
    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;
    }
    MI_Instance* searchInstance = NULL;
    miResult = CreateSearchInstance(&miSession, L"root\\cimv2", L"Win32_Process", MI_TRUE, &searchInstance);
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"Failed to create a keyed instance for the operation. MI_Result: %ld\n", miResult);
        return -1;
    }
    GetInstance(&miSession, L"root\\cimv2", L"Win32_Process", searchInstance);    
    miResult = MI_Instance_Delete(searchInstance);
    if (miResult != MI_RESULT_OK)
    {
        wprintf(L"MI_Instance_Delete failed. MI_Result: %ld\n", miResult);
        return -1;
    }
    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;
}