Zugreifen auf vorinstallierte WMI-Leistungsklassen

Das WMI-Repository enthält vorinstallierte Leistungsklassen für alle Leistungsbibliotheksobjekte. Beispielsweise stellen Instanzen der Rohdatenleistungsklasse Win32_PerfRawData_PerfProc_Process Prozesse dar. Dieses Leistungsobjekt ist im Systemmonitor als Prozessobjekt sichtbar.

Die Eigenschaft PageFaultsPerSec von Win32_PerfRawData_PerfProc_Process stellt den Leistungsindikator Seitenfehler pro Sekunde für den Prozess dar. Die Klassen Win32_PerfFormattedData enthalten die berechneten Datenwerte, die im Systemmonitor (Perfmon.exe) angezeigt werden. Der Wert der Eigenschaft PageFaultsPerSec von Win32_PerfFormattedData_PerfProc_Process ist identisch mit dem Wert, wenn er im Systemmonitor angezeigt wird.

Verwenden Sie entweder die COM-API für WMI oder die Skript-API für WMI, um über die Leistungsindikatorklassen auf Leistungsdaten zuzugreifen. In beiden Fällen ist ein Aktualisierungsobjekt erforderlich, um jedes Datenbeispiel abzurufen. Weitere Informationen und Skriptcodebeispiele für die Verwendung von Aktualisierungen und den Zugriff auf Leistungsklassen finden Sie unter WMI-Aufgaben: Leistungsüberwachung. Weitere Informationen finden Sie unter Zugreifen auf Leistungsdaten im Skript.

Zugreifen auf Leistungsdaten aus C++

Im folgenden C++-Codebeispiel wird der Leistungsindikatoranbieter verwendet, um auf vordefinierte Hochleistungsklassen zuzugreifen. Es erstellt ein Aktualisierungsobjekt und fügt dem Aktualisierungsprogramm ein Objekt hinzu. Das Objekt ist eine Instanz vom Typ Win32_PerfRawData_PerfProc_Process, das die Leistung eines bestimmten Prozesses überwacht. Der Code liest nur eine Zählereigenschaft im Prozessobjekt, die Eigenschaft VirtualBytes . Der Code erfordert die folgenden Verweise und #include-Anweisungen für eine ordnungsgemäße Kompilierung.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

Das folgende Verfahren zeigt, wie Sie von einem Hochleistungsanbieter in C++ auf Daten zugreifen.

So greifen Sie auf Daten von einem Hochleistungsanbieter in C++ zu

  1. Stellen Sie eine Verbindung mit dem WMI-Namespace her, und legen Sie die WMI-Sicherheit mithilfe eines Aufrufs von IWbemLocator::ConnectServer und CoSetProxyBlanket fest.

    Dieser Schritt ist ein Standardschritt zum Erstellen einer beliebigen WMI-Clientanwendung. Weitere Informationen finden Sie unter Erstellen einer WMI-Anwendung mit C++.

  2. Erstellen Sie ein Aktualisierungsobjekt mithilfe von CoCreateInstance mit CLSID_WbemRefresher. Fordern Sie eine Schnittstelle IWbemConfigureRefresher über die Methode QueryInterface an. Fordern Sie eine Schnittstelle IWbemRefresher über die Methode QueryInterface an.

    Die Schnittstelle IWbemRefresher ist die Standard-Schnittstelle für das WMI Aktualisierungsobjekt.

    Das folgende Codebeispiel in C++ zeigt, wie Sie IWbemConfigureRefresher abrufen.

    IWbemRefresher* pRefresher = NULL;
    
    HRESULT hr = CoCreateInstance(
        CLSID_WbemRefresher,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IWbemRefresher,
        (void**) &pRefresher);
    
    IWbemConfigureRefresher* pConfig = NULL;
    
    pRefresher->QueryInterface( 
        IID_IWbemConfigureRefresher,
        (void**) &pConfig
      );
    
  3. Fügen Sie der Aktualisierung über einen Aufruf der Methode IWbemConfigureRefresher::AddObjectByPath ein Aktualisierungsobjekt hinzu.

    Wenn Sie der Aktualisierung ein Objekt hinzufügen, aktualisiert WMI das Objekt immer dann, wenn Sie die Methode IWbemRefresher::Refresh aufrufen. Das Objekt, das Sie hinzufügen, legt den Anbieter in seinen Klassenqualifizierern fest.

    Im folgenden Codebeispiel in C++ wird das Aufrufen von AddObjectByPath veranschaulicht.

    IWbemClassObject* pObj = NULL;
    IWbemServices* pNameSpace = NULL;
    
    // Add the instance to be refreshed.
    hr = pConfig->AddObjectByPath(
         pNameSpace,
         L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"",
         0L,
         NULL,
         &pObj,
         NULL
    );
    if (FAILED(hr))
    {
       cout << "Could not add object. Error code: 0x"
            << hex << hr << endl;
       pNameSpace->Release();
       return hr;
    }
    
  4. Um einen schnelleren Zugriff auf das Objekt einzurichten, stellen Sie über QueryInterface auf der Schnittstelle IWbemClassObject eine Verbindung mit der Schnittstelle IWbemObject her.

    Im folgenden C++-Codebeispiel wird gezeigt, wie Sie mithilfe von IWbemObjectAccess anstelle von IWbemClassObject einen Zeiger auf das Objekt abrufen.

        // For quick property retrieval, use IWbemObjectAccess.
        IWbemObjectAccess* pAcc = NULL;
        pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAcc );
        // This is not required.
        pObj->Release();
    

    Die Schnittstelle IWbemObjectAccess erhöht die Leistung, da Sie Handles für bestimmte Zählereigenschaften abrufen können. Dazu müssen Sie das Objekt im Code sperren und entsperren. Dies ist ein Vorgang, den IWbemClassObject für jeden Eigenschaftenzugriff ausführt.

  5. Rufen Sie die Handles der zu untersuchenden Eigenschaften mithilfe von Aufrufen der Methode IWbemObjectAccess::GetPropertyHandle ab.

    Eigenschaftshandles sind für alle Instanzen einer Klasse identisch. Das bedeutet, dass Sie den Eigenschaftshandle verwenden, den Sie von einer bestimmten Instanz für alle Instanzen einer bestimmten Klasse abrufen. Sie können auch einen Handle aus einem Klassenobjekt abrufen, um Eigenschaftswerte aus einem Instanzobjekt abzurufen.

    Das folgende C++-Codebeispiel zeigt, wie ein Eigenschaftshandle abgerufen wird.

        // Get a property handle for the VirtualBytes property
        long lVirtualBytesHandle = 0;
        DWORD dwVirtualBytes = 0;
        CIMTYPE variant;
    
        hr = pAcc->GetPropertyHandle(L"VirtualBytes",
             &variant,
             &lVirtualBytesHandle 
        );
        if (FAILED(hr))
        {
           cout << "Could not get property handle. Error code: 0x"
                << hex << hr << endl;
           return hr;
        }
    
  6. Erstellen Sie eine Programmierschleife, die die folgenden Aktionen ausführt:

    • Aktualisieren Sie das Objekt mit einem Aufruf von IWbemRefresher::Refresh mithilfe des Zeigers, der im vorherigen Aufruf von CoCreateInstance erstellt wurde.

      In diesem Aufruf aktualisiert der WMI-Refresher das Clientobjekt mithilfe der vom Anbieter bereitgestellten Daten.

    • Führen Sie alle erforderlichen Aktionen für das Objekt aus, z. B. das Abrufen eines Eigenschaftsnamens, Datentyps oder Werts.

      Sie können über den zuvor abgerufene Eigenschaftshandle auf die Eigenschaft zugreifen. Aufgrund des Aktualisierungsaufrufs aktualisiert WMI die Eigenschaft jedes Mal über die Schleife.

Das folgende C++-Beispiel zeigt die Verwendung der WMI-Hochleistungs-API.

// Get the local locator object
IWbemServices* pNameSpace = NULL;
IWbemLocator* pWbemLocator = NULL;
CIMTYPE variant;
VARIANT VT;

CoCreateInstance( CLSID_WbemLocator, NULL,
    CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**) &pWbemLocator
);

// Connect to the desired namespace
BSTR bstrNameSpace = SysAllocString( L"\\\\.\\root\\cimv2" );

HRESULT hr = WBEM_S_NO_ERROR;

hr = pWbemLocator->ConnectServer(
     bstrNameSpace,      // Namespace name
     NULL,               // User name
     NULL,               // Password
     NULL,               // Locale
     0L,                 // Security flags
     NULL,               // Authority
     NULL,               // Wbem context
     &pNameSpace         // Namespace
);

if ( SUCCEEDED( hr ) )
{
    // Set namespace security.
    IUnknown* pUnk = NULL;
    pNameSpace->QueryInterface( IID_IUnknown, (void**) &pUnk );

    hr = CoSetProxyBlanket(
         pNameSpace, 
         RPC_C_AUTHN_WINNT, 
         RPC_C_AUTHZ_NONE, 
         NULL, 
         RPC_C_AUTHN_LEVEL_DEFAULT, 
         RPC_C_IMP_LEVEL_IMPERSONATE,
         NULL, 
         EOAC_NONE 
    );
    if (FAILED(hr))
    {
       cout << "Cannot set proxy blanket. Error code: 0x"
            << hex << hr << endl;
       pNameSpace->Release();
       return hr;
    }

    hr = CoSetProxyBlanket(pUnk, 
         RPC_C_AUTHN_WINNT, 
         RPC_C_AUTHZ_NONE, 
         NULL, 
         RPC_C_AUTHN_LEVEL_DEFAULT, 
         RPC_C_IMP_LEVEL_IMPERSONATE,
         NULL, 
         EOAC_NONE 
    );
    if (FAILED(hr))
    {
       cout << "Cannot set proxy blanket. Error code: 0x"
            << hex << hr << endl;
       pUnk->Release();
       return hr;
    }

    // Clean up the IUnknown.
    pUnk->Release();

    IWbemRefresher* pRefresher = NULL;
    IWbemConfigureRefresher* pConfig = NULL;

    // Create a WMI Refresher and get a pointer to the
    // IWbemConfigureRefresher interface.
    CoCreateInstance(CLSID_WbemRefresher, 
                     NULL,
                     CLSCTX_INPROC_SERVER, 
                     IID_IWbemRefresher, 
                     (void**) &pRefresher 
    );
    
    pRefresher->QueryInterface(IID_IWbemConfigureRefresher,
                               (void**) &pConfig );

    IWbemClassObject* pObj = NULL;

    // Add the instance to be refreshed.
    pConfig->AddObjectByPath(
       pNameSpace,
       L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"",
       0L,
       NULL,
       &pObj,
       NULL 
    );
    if (FAILED(hr))
    {
       cout << "Cannot add object. Error code: 0x"
            << hex << hr << endl;
       pNameSpace->Release();
       
       return hr;
    }

    // For quick property retrieval, use IWbemObjectAccess.
    IWbemObjectAccess* pAcc = NULL;
    pObj->QueryInterface(IID_IWbemObjectAccess, 
                         (void**) &pAcc );

    // This is not required.
    pObj->Release();

    // Get a property handle for the VirtualBytes property.
    long lVirtualBytesHandle = 0;
    DWORD dwVirtualBytes = 0;

    pAcc->GetPropertyHandle(L"VirtualBytes", 
                            &variant, 
                            &lVirtualBytesHandle );

    // Refresh the object ten times and retrieve the value.
    for( int x = 0; x < 10; x++ )
    {
        pRefresher->Refresh( 0L );
        pAcc->ReadDWORD( lVirtualBytesHandle, &dwVirtualBytes );
        printf( "Process is using %lu bytes\n", dwVirtualBytes );
        // Sleep for a second.
        Sleep( 1000 );
    }
    // Clean up all the objects.
    pAcc->Release();
    // Done with these too.
    pConfig->Release();
    pRefresher->Release();
    pNameSpace->Release();
}
SysFreeString( bstrNameSpace );
pWbemLocator->Release();

Leistungsindikatorklassen

WMI-Aufgaben: Leistungsüberwachung