EternalWindows
PDH / ブラウジングカウンタ

アプリケーションがPDHを用いる理由は多くの場合、 特定のオブジェクトのカウンタの値を取得することにありますから、 基本的にその他のオブジェクトやカウンタに目を向けることはないと思われます。 しかし、システム全体のパフォーマンスを取得しようとした場合、 それに関わるオブジェクトやカウンタの数は非常に膨大であり、 これまでのようにカウンタパスを静的に宣言するという方法には限界があります。 このような場合、全てのオブジェクトとカウンタを選択できるダイアログを表示し、 ユーザー自らそれらを選択してもらうという方法がありますが、 PDH特有のオブジェクとカウンタの概念をユーザーに強いることになるので、 場合によってはこの方法も不適切であるといえるかもしれません。 ダイアログを表示するのは、次に示すPdhBrowseCountersです。

PDH_STATUS PdhBrowseCounters(
  PPDH_BROWSE_DLG_CONFIG pBrowseDlgData 
);

pBrowseDlgDataは、PDH_BROWSE_DLG_CONFIG構造体のアドレスです。 この構造体は、ダイアログの表示内容を表すと共に、 ユーザーが選択したオブジェクトやカウンタを示すカウンタパスを受け取ります。 次に、その定義を示します。

typedef struct _BrowseDlgConfig {
  // Configuration flags
  DWORD   bIncludeInstanceIndex:1,
          bSingleCounterPerAdd:1,
          bSingleCounterPerDialog:1,
          bLocalCountersOnly:1,
          bWildCardInstances:1,
          bHideDetailBox:1,
          bInitializePath:1,
          bDisableMachineSelection:1,
          bIncludeCostlyObjects:1,
          bShowObjectBrowser:1,
          bReserved:23;

  HWND                hWndOwner;
  LPTSTR              szDataSource;
  LPTSTR              szReturnPathBuffer;
  DWORD               cchReturnPathLength;
  CounterPathCallBack pCallBack;
  DWORD_PTR           dwCallBackArg;
  PDH_STATUS          CallBackStatus;
  DWORD               dwDefaultDetailLevel;
  LPTSTR              szDialogBoxCaption;
} PDH_BROWSE_DLG_CONFIG, *PPDH_BROWSE_DLG_CONFIG;

bIncludeInstanceIndexは、カウンタパスのインスタンスにインデックスを付けるかどうかです。 FALSEの場合は、#1のようなインデックスが付くことはありません。 bSingleCounterPerAddは、1つのカウンタのみ選択可能にするかどうかです。 FALSEの場合は、複数のカウンタを選択できるようになり、 後述するszReturnPathBufferが複数のカウンタパスで構成されることになります。 なお、TRUEの場合でも複数選択のハイライトは表示されますが、 取得できるカウンタパスは1つのみです。 bSingleCounterPerDialogは、1つのオブジェクトのカウンタのみを選択可能にするかどうかです。 FALSEの場合、OKボタンが追加ボタンへと変更され、追加ボタン押下後も、 任意のオブジェクトのカウンタを追加することができます。 追加を終了する場合は、ウインドウの閉じるボタンを押します。 bLocalCountersOnlyは、カウンタパスにコンピュータ名を付けるかどうかです。 FALSEの場合、コンピュータ名が付くことになります。 bHideDetailBoxは、カウンタの詳細レベルを決定するかどうかです。 FALSEの場合、詳細レベルを選択するためのコンボボックスが表示されます。 bInitializePathは、デフォルトで選択するカウンタを決定するかどうかです。 TRUEの場合、予め初期化しておいたszReturnPathBufferメンバを基にカウンタが選択され、 FALSEの場合はPdhGetDefaultPerfObjectとPdhGetDefaultPerfCounterで得られる オブジェクトのカウンタがデフォルトで選択されます。 bDisableMachineSelectionは、モニタするコンピュータを決定するかどうかです。 TRUEの場合、コンピュータ名を選択するコンボボックスが使用不可能になります。 bIncludeCostlyObjectsは、よく分からないメンバです。 TRUEの場合、ダイアログを表示するまでの時間が非常に長くなり、 選択できるオブジェクトが増えることになります。 しかし、その増えたオブジェクトは既に存在しているオブジェクトと同じ名前を持ち、 何故かOKボタンで選択することができません。 bShowObjectBrowserは、カウンタを選択せずオブジェクトのみを選択するかどうかです。 TRUEの場合、szReturnPathBufferで得られるカウンタパスは、 カウンタとインスタンスの部分が*表記となります。 hWndOwnerは、ダイアログの親ウインドウとするウインドウのハンドルを示します。 szDataSourceは、データソースを示す文字列を指定します。 szReturnPathBufferは、カウンタパスを受け取るバッファへのアドレスです。 cchReturnPathLengthは、szReturnPathBufferのサイズを指定します。 pCallBackは、コールバック関数のアドレスを指定します。 このコールバック関数はユーザーがOKボタン、または追加ボタンを押したときに呼ばれ、 後者の場合だと、ユーザーが選択したカウンタを追跡することができます。 コールバック関数の戻り値は、基本的にERROR_SUCCESSを返すことになります。 dwCallBackArgは、pCallBackに渡したい引数を指定します。 pCallBackでは、ユーザーが選択したカウンタを確認したいはずですから、 少なくともここには、szReturnPathBufferが指すバッファを指定することになると思われます。 CallBackStatusは、コールバック関数の処理を示す状態値が格納されます。 値がERROR_SUCCESSである場合、szReturnPathBufferは有効な文字列が格納されています。 dwDefaultDetailLevelは、カウンタのフィルタに利用する詳細レベルを指定します。 szDialogBoxCaptionhは、ダイアログのタイトルです。

今回のプログラムは、PdhBrowseCountersによってカウンタパスを取得します。

#include <windows.h>
#include <pdh.h>

#pragma comment (lib, "pdh.lib")

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	TCHAR                 szBuf[256];
	TCHAR                 szCounterPath[1024];
	PDH_HQUERY            hQuery;
	PDH_HCOUNTER          hCounter;
	PDH_FMT_COUNTERVALUE  fmtValue;
	PDH_BROWSE_DLG_CONFIG browseConfig;

	browseConfig.bIncludeInstanceIndex    = FALSE;
	browseConfig.bSingleCounterPerAdd     = TRUE;
	browseConfig.bSingleCounterPerDialog  = TRUE;
	browseConfig.bLocalCountersOnly       = TRUE;
	browseConfig.bWildCardInstances       = TRUE;
	browseConfig.bHideDetailBox           = TRUE;
	browseConfig.bInitializePath          = FALSE;
	browseConfig.bDisableMachineSelection = FALSE;
	browseConfig.bIncludeCostlyObjects    = FALSE;
	browseConfig.bShowObjectBrowser       = FALSE;
	browseConfig.hWndOwner                = NULL;
	browseConfig.szDataSource             = NULL;
	browseConfig.szReturnPathBuffer       = szCounterPath;
	browseConfig.cchReturnPathLength      = sizeof(szCounterPath);
	browseConfig.pCallBack                = NULL;
	browseConfig.dwCallBackArg            = 0;
	browseConfig.CallBackStatus           = ERROR_SUCCESS;
	browseConfig.dwDefaultDetailLevel     = PERF_DETAIL_WIZARD;
	browseConfig.szDialogBoxCaption       = TEXT("Select Counter");

	if (PdhBrowseCounters(&browseConfig) != ERROR_SUCCESS)
		return 0;

	PdhOpenQuery(NULL, 0, &hQuery);
	
	PdhAddCounter(hQuery, szCounterPath, 0, &hCounter);
	
	PdhCollectQueryData(hQuery);
	
	PdhGetFormattedCounterValue(hCounter, PDH_FMT_LONG, NULL, &fmtValue);
	
	wsprintf(szBuf, TEXT("%d"), fmtValue.longValue);
	MessageBox(NULL, szBuf, TEXT("OK"), MB_OK);
	
	PdhCloseQuery(hQuery);

	return 0;
}

ブラウザダイアログのインスタンスの一覧を見てみると分かることですが、 一部のオブジェクトは_Totalという擬似インスタンスが選択可能となっています。 このインスタンスを指定した場合、全てのインスタンスにおけるカウンタの値の 合計値を取得することができるため、何らかの総数を知る際に応用が効くと思われます。 たとえば、オブジェクトにProcess、カウンタにHandle Countを指定したならば、 現在システムでどれだけのハンドルがオープンされているかを取得できます。


戻る