WMI のプレインストール済みパフォーマンス クラスへのアクセス

WMI リポジトリには、すべてのパフォーマンス ライブラリ オブジェクトに対応した、プレインストール済みのパフォーマンス クラスが含まれています。 たとえば、生データ パフォーマンス クラス Win32_PerfRawData_PerfProc_Process のインスタンスは、プロセスを表します。 このパフォーマンス オブジェクトは、システム モニターで Process オブジェクトとして表示されます。

Win32_PerfRawData_PerfProc_ProcessPageFaultsPerSec プロパティは、プロセスの 1 秒あたりの Page Faults パフォーマンス カウンターを表します。 Win32_PerfFormattedData クラスには、システム モニター (Perfmon.exe) に表示される計算済みのデータ値が含まれます。 Win32_PerfFormattedData_PerfProc_ProcessPageFaultsPerSec プロパティの値は、システム モニターに表示される場合のものと同じです。

パフォーマンス カウンター クラスを使用してパフォーマンス データにアクセスするには、WMI 用 COM API または WMI 用スクリプト API を使用します。 どちらの場合も、各データ サンプルを取得するには "リフレッシャー" オブジェクトが必要です。 リフレッシャーの使用とパフォーマンス クラスへのアクセスに関する詳細とスクリプト コード例については、「WMI タスク: パフォーマンス監視」を参照してください。 詳細については、「スクリプトでのパフォーマンス データへのアクセス」を参照してください。

C++ からのパフォーマンス データへのアクセス

次の C++ コード例では、パフォーマンス カウンター プロバイダーを使用して、定義済みのハイパフォーマンス クラスにアクセスしています。 リフレッシャー オブジェクトを作成し、オブジェクトをリフレッシャーに追加しています。 このオブジェクトは、特定のプロセスのパフォーマンスを監視する Win32_PerfRawData_PerfProc_Process インスタンスです。 コードは、プロセス オブジェクトのカウンター プロパティを 1 つだけ読み取ります (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 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 メソッドを呼び出して、リフレッシャーにオブジェクトを追加します。

    リフレッシャーにオブジェクトを追加すると、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++ コード例は、IWbemClassObject ではなく IWbemObjectAccess を使用してオブジェクトへのポインターを取得する方法を示したものです。

        // 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. 次のアクションを実行するプログラミング ループを作成します。

    • CoCreateInstance に対する前回の呼び出しで作成されたポインターを使用して、IWbemRefresher::Refresh の呼び出しによってオブジェクトを更新する。

      この呼び出しでは、WMI Refresher が、プロバイダーの提供するデータを使用してクライアント オブジェクトを更新します。

    • 必要に応じて、オブジェクトに対する任意のアクションを実行する (プロパティ名、データ型、値の取得など)。

      プロパティには、先ほど取得したプロパティ ハンドルを使用してアクセスできます。 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 タスク: パフォーマンスの監視