How to: Enumerate All Instances of a Class (C/C++)
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;
}