Доступ к предварительно установленным классам производительности WMI

Репозиторий WMI содержит предустановленные классы производительности для всех объектов библиотеки производительности. Например, экземпляры класса производительности необработанных данных Win32_PerfRawData_PerfProc_Process представляют процессы. Этот объект производительности отображается в системном мониторе как объект Process.

Свойство PageFaultsPerSecWin32_PerfRawData_PerfProc_Process представляет счетчик производительности ошибок страниц в секунду для процесса. Классы Win32_PerfFormattedData содержат вычисляемые значения данных, отображаемые в системном мониторе (Perfmon.exe). Значение свойства PageFaultsPerSecWin32_PerfFormattedData_PerfProc_Process совпадает с значением, отображаемым в системном мониторе.

Используйте COM API для WMI или API скриптов для WMI для доступа к данным производительности через классы счетчиков производительности. В обоих случаях для получения каждого примера данных требуется объект средства обновления . Дополнительные сведения и примеры кода скриптов для использования средств обновления и доступа к классам производительности см. в разделе Задачи WMI: мониторинг производительности. Дополнительные сведения см. в разделе Доступ к данным о производительности в скрипте.

Доступ к данным о производительности из C++

В следующем примере кода C++ поставщик счетчиков производительности используется для доступа к предопределенным высокопроизводительным классам. Он создает объект средства обновления и добавляет объект в средство обновления. Объект является экземпляром Win32_PerfRawData_PerfProc_Process , который отслеживает производительность определенного процесса. Код считывает только одно свойство счетчика в объекте процесса, свойство VirtualBytes . Для правильной компиляции кода требуются следующие ссылки и инструкции #include .

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

В следующей процедуре показано, как получить доступ к данным из высокопроизводительного поставщика в C++.

Доступ к данным от высокопроизводительного поставщика в C++

  1. Установите подключение к пространству имен WMI и настройте безопасность WMI с помощью вызова IWbemLocator::ConnectServer и CoSetProxyBlanket.

    Этот шаг является стандартным для создания любого клиентского приложения WMI. Дополнительные сведения см. в статье Создание приложения WMI с помощью C++.

  2. Создайте объект средства обновления с помощью CoCreateInstance с CLSID_WbemRefresher. Запросите интерфейс IWbemConfigureRefresher с помощью метода QueryInterface . Запросите интерфейс IWbemRefresher с помощью метода QueryInterface .

    Интерфейс IWbemRefresher — это интерфейс main для объекта WMI Refresher.

    В следующем примере кода C++ показано, как получить IWbemConfigureRefresher.

    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. Добавьте объект в средство обновления с помощью вызова метода IWbemConfigureRefresher::AddObjectByPath .

    При добавлении объекта в средство обновления WMI обновляет объект при каждом вызове метода IWbemRefresher::Refresh . Добавляемый объект обозначает поставщика в его квалификаторе класса.

    В следующем примере кода C++ показано, как вызвать AddObjectByPath.

    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. Чтобы настроить более быстрый доступ к объекту, подключитесь к интерфейсу IWbemObjectAccess через QueryInterface в интерфейсе IWbemClassObject .

    В следующем примере кода C++ показано, как получить указатель на объект с помощью IWbemObjectAccess вместо IWbemClassObject.

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

    Интерфейс IWbemObjectAccess повышает производительность, так как вы можете получить дескриптора для определенных свойств счетчиков и требует блокировки и разблокировки объекта в коде, который является операцией, выполняемой IWbemClassObject для доступа к каждому свойству.

  5. Получение дескрипторов проверяемых свойств с помощью вызовов метода IWbemObjectAccess::GetPropertyHandle .

    Дескриптора свойств одинаковы для всех экземпляров класса. Это означает, что для всех экземпляров определенного класса используется дескриптор свойства, полученный из определенного экземпляра. Вы также можете получить дескриптор из объекта класса для получения значений свойств из объекта экземпляра.

    В следующем примере кода C++ показано, как получить дескриптор свойства.

        // 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. Создайте цикл программирования, который выполняет следующие действия:

    • Обновите объект с помощью вызова IWbemRefresher::Refresh с помощью указателя, созданного в предыдущем вызове CoCreateInstance.

      В этом вызове средство обновления WMI обновляет клиентский объект, используя данные, предоставляемые поставщиком.

    • При необходимости выполняйте любое действие с объектом, например получение имени свойства, типа данных или значения.

      Доступ к свойству можно получить с помощью дескриптора свойства, полученного ранее. Из-за вызова Refresh WMI обновляет свойство каждый раз в цикле .

В следующем примере C++ показано, как использовать высокопроизводительный API WMI.

// 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();

Классы счетчиков производительности

Задачи WMI: мониторинг производительности