访问 WMI 预安装的性能类

WMI 存储库包含所有性能库对象的预安装性能类。 例如,原始数据性能类的实例 Win32_PerfRawData_PerfProc_Process 表示进程。 此性能对象作为“进程”对象在系统监视器中可见。

Win32_PerfRawData_PerfProc_Process 的“PageFaultsPerSec”属性表示进程的每秒页面错误数性能计数器。 Win32_PerfFormattedData 类包含系统监视器 (Perfmon.exe) 中显示的计算数据值。 Win32_PerfFormattedData_PerfProc_Process 的“PageFaultsPerSec”属性的值与在系统监视器中显示的值相同。

使用适用于 WMI 的 COM API用于 WMI 的脚本 API 通过性能计数器类访问性能数据。 这两种情况都需要刷新程序对象来获取每个数据示例。 有关使用刷新程序和访问性能类的详细信息和脚本代码示例,请参阅 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 命名空间的连接,并使用对 IWbemLocator::ConnectServerCoSetProxyBlanket 的调用设置 WMI 安全性。

    此步骤是创建任何 WMI 客户端应用程序的标准步骤。 有关详细信息,请参阅使用 C++ 创建 WMI 应用程序

  2. 使用 CoCreateInstance 和 CLSID_WbemRefresher 创建刷新程序对象。 通过 QueryInterface 方法请求 IWbemConfigureRefresher 接口。 通过 QueryInterface 方法请求 IWbemRefresher 接口。

    IWbemRefresher 接口是 WMI 刷新程序对象的主接口。

    以下 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 方法将对象添加到刷新程序。

    向刷新程序添加对象时,每当调用 IWbemRefresher::Refresh 方法时,WMI 将刷新对象。 添加的对象在其类限定符中指定提供程序。

    以下 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. 若要设置对对象的更快访问,请通过 IWbemClassObject 接口上的 QueryInterface 连接到 IWbemObjectAccess 接口。

    以下 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++ 示例演示如何使用 WMI 高性能 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();

性能计数器类

WMI 任务:性能监视