MMC 2.0 and WMI: Implementation Details

The procedures outlined in this section describe how to connect to a WMI namespace, retrieve and display information, and receive asynchronous event notifications when the underlying data in the namespace changes.

Be aware that this discussion does not cover how to implement WMI-related interfaces and methods.

To connect to a WMI namespace

  1. Connect to the desired WMI namespace on the desired host computer. To simplify the connection process, use the IWbemLocator interface and its ConnectServer method. This method allows WMI client applications (snap-ins) to obtain a pointer to an IWbemServices object bound to the desired namespace on the desired target computer.
  2. To use the IWbemLocator interface:
    • Use the COM API function CoCreateInstance to create an instance of the IWbemLocator interface in-process. CoCreateInstance returns an IWbemLocator interface pointer, which you can use to call the ConnectServer method.
    • Call the ConnectServer method to specify the WMI namespace that the snap-in connects to. The method returns a pointer to an IWbemServices object bound to the desired namespace. This is the "services pointer" that the snap-in uses to access WMI services for the namespace.

Most information in WMI is represented as instances of a particular WMI class. The class is the definition of what an object looks like, while the instance is an actual occurrence of the class that contains specific properties. It is possible to enumerate all instances of a given class, request a subset of the instances that match the criteria of a query or retrieve a specific instance based on a unique set of key values.

To retrieve information from WMI

  1. To enumerate all instances of a known class, call CreateInstanceEnum on the snap-in's IWbemServices pointer. The CreateInstanceEnum method returns an IEnumWbemClassObject pointer.
  2. Call the Next method on this IEnumWbemClassObject pointer to get each successive IWbemClassObject pointer.
  3. For smarter filtering, call the ExecQuery method on the IWbemServices pointer, which enables you to use WQL, a subset of the SQL query language, to narrow down the results of the query to the items of interest.
  4. To retrieve a specific instance of a class, call the GetObject method on the IWbemServices pointer, which retrieves that desired instance directly using the keys specified.
  5. Use the various methods of IWbemClassObject to retrieve property, method and qualifier information as desired.

Methods are actions or operations that can be executed against a class or instances of a class. Most methods are defined to operate on an instance of a class. An example of this would be a "compress" method that can be run on instances of a data file class instance. When run, the method would attempt to use a compression algorithm to reduce the size of the file stored on the system.

To invoke a WMI Method

  1. Prepare the input and output parameters by calling the GetMethod method on the IWbemClassObject pointer. The input parameter is an IWbemClassObject object populated with the required properties. It is not necessary to retrieve the output parameter object before invoking the method. The method will populate the output class as required. Be aware that GetMethod must be called on a CIM Class Definition type of IWbemClassObject; not on a CIM Instance type.
  2. Use the appropriate methods on IWbemClassObject to fill in the input parameter's properties.
  3. Call ExecMethod on the IWbemServices pointer to invoke the method.
  4. Examine the error codes from ExecMethod itself and the output parameter's properties as appropriate for the particular method.

The Steps outlined in this procedure address the fact that WMI events are received on a WMI-owned thread. By using a snap-in-defined window message, the snap-in can transfer flow control to the main MMC thread where MMC interfaces can be called in response to the WMI event. Be aware that MMC-defined COM interfaces cannot be marshaled.

To receive asynchronous event notifications

  1. Implement the WMI interface IWbemObjectSink.

  2. For security reasons (see "Asynchronous Event Notification and Security Issues" in the " MMC and WMI" topic) snap-ins must use the IUnsecuredApartment interface to bind the snap-in's local object sink (an instance of its IWbemObjectSink implementation) to an unsecured object sink that receives the event notifications. The IUnsecuredApartment interface contains the CreateObjectStub method, which the snap-in can use to create the unsecured object sink.

  3. Using the IWbemServices services pointer obtained in the call to IWbemLocator::ConnectServer, call the IWbemServices::ExecNotificationQueryAsync method to register for "temporary" WMI events of interest. In the call to ExecNotificationQueryAsync, verify that the pResponseHandler parameter contains a pointer to the unsecured object sink created in the call to IUnsecuredApartment::CreateObjectStub.

    As registered events become available, WMI calls the Indicate method on the IWbemObjectSink object supplied in the call to ExecNotificationQueryAsync.

  4. Handle calls to the snap-in's IWbemObjectSink::Indicate method.