パフォーマンス・カウンタの一括取得 – プログラミング – Home

パフォーマンス・カウンタの一括取得
 
通知
すべてクリア

[解決済] パフォーマンス・カウンタの一括取得


オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

VC2003.NET
Windows XP

PdhAddCounter で複数のカウンタ・パスを追加
PdhCollectQueryData でデータ収集
PdhGetFormattedCounterValue で個別に取得することは出来る。
でも PdhGetFormattedCounterArray で一括取得がうまくいかない。

下に全ソースを載せるので間違っている場合には
その箇所などを教えて下さい。
よろしくお願いします。

#include <stdio.h>
#include <Windows.h>
#include <Pdh.h>

// 個別取得(正常)
VOID GetMemoryInfo1( LPCTSTR CountPath[] )
{
PDH_HQUERY hQuery;
PDH_HCOUNTER hCounter[ 10 ] = { 0 };
PDH_FMT_COUNTERVALUE fmtValue[ 10 ] = { 0 };

if ( PdhOpenQuery(NULL,0,&hQuery) == ERROR_SUCCESS ){
PdhAddCounter( hQuery, CountPath[0], 0, &hCounter[0] );
PdhAddCounter( hQuery, CountPath[1], 0, &hCounter[1] );
PdhAddCounter( hQuery, CountPath[2], 0, &hCounter[2] );
PdhCollectQueryData( hQuery );
PdhGetFormattedCounterValue( hCounter[0], PDH_FMT_LONG, NULL, &fmtValue
[0] );
PdhGetFormattedCounterValue( hCounter[1], PDH_FMT_LONG, NULL, &fmtValue
[1] );
PdhGetFormattedCounterValue( hCounter[2], PDH_FMT_LONG, NULL, &fmtValue
[2] );
PdhCloseQuery( hQuery );
printf( %-24s = %10ld B\n, CountPath[0], fmtValue[0].longValue );
printf( %-24s = %10ld KB\n, CountPath[1], fmtValue[1].longValue );
printf( %-24s = %10ld MB\n, CountPath[2], fmtValue[2].longValue );
printf( \n );
}
}

// 一括取得(異常)
VOID GetMemoryInfo2( LPCTSTR CountPath[] )
{
PDH_HQUERY hQuery;
PDH_HCOUNTER hCounter;
PDH_FMT_COUNTERVALUE_ITEM fmtArray[ 10 ] = { 0 };
DWORD dwArray = sizeof(fmtArray);
DWORD dwCount;

if ( PdhOpenQuery(NULL,0,&hQuery) == ERROR_SUCCESS ){
PdhAddCounter( hQuery, CountPath[0], 0, &hCounter );
PdhAddCounter( hQuery, CountPath[1], 0, &hCounter );
PdhAddCounter( hQuery, CountPath[2], 0, &hCounter );
PdhCollectQueryData( hQuery );
PdhGetFormattedCounterArray( hCounter, PDH_FMT_LONG, &dwArray,
&dwCount, fmtArray );
PdhCloseQuery( hQuery );
printf( %-24s = %10ld B\n, CountPath[0], fmtArray
[0].FmtValue.longValue );
printf( %-24s = %10ld KB\n, CountPath[1], fmtArray
[1].FmtValue.longValue );
printf( %-24s = %10ld MB\n, CountPath[2], fmtArray
[2].FmtValue.longValue );
printf( dwCount = %lu 個\n, dwCount );
printf( \n );
}
}

// メイン関数
int main( void )
{
static LPCTSTR CountPath[] = {
\\Memory\\Available Bytes,
\\Memory\\Available KBytes,
\\Memory\\Available MBytes,
NULL,
};

GetMemoryInfo1( CountPath );
GetMemoryInfo2( CountPath );
return 0;
}


引用未解決
トピックタグ
nori
 nori
(@nori)
ゲスト
結合: 23年前
投稿: 9
 

全く知りませんが。
一応MSDNを見ての感想。

PdhGetFormattedCounterArrayの戻り値は何ですか?
# PDH_MORE_DATAになってるとかは無いですか?

dwArray,dwCount正しい値は戻ってきていますか?


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

noriさま。
ご回答ありがとうございます。

>PdhGetFormattedCounterArrayの戻り値は何ですか?
># PDH_MORE_DATAになってるとかは無いですか?
ERROR_SUCCESS が戻ってきました。
よって正常。

>dwArray,dwCount正しい値は戻ってきていますか?
PdhGetFormattedCounterArray 実行前 dwArray = 240 個
PdhGetFormattedCounterArray 実行後 dwArray = 24 個 dwCount = 1 個

// 正常な値(個別)
fmtValue[0] = 307601408 B
fmtValue[1] = 300392 KB
fmtValue[2] = 293 MB

// 異常な値(一括)
fmtArray[0] = 293 B
fmtArray[1] = 0 KB
fmtArray[2] = 0 MB

この結果より PdhAddCounter の使い方に問題があるのかと最初思いました。
でも色々と試しましたが解決できませんでした。
(1)PdhAddCounter に共通の hCounter をセットした
(2)PdhAddCounter に別々の hCounter[配列] をセットした

MSDNサイトの英語版に PdhGetFormattedCounterArray
のサンプルが載っていた。
http://msdn.microsoft.com/en-us/library/aa372633(VS.85).aspx
でもこのサンプルでは PdhAddCounter 部分がない。
google検索しても PdhGetFormattedCounterArray があまりヒットしない。
何がいけないのですかね?


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

追加。

PdhAddCounter も戻り値を調べましたら ERROR_SUCCESS が戻ってきました。
こちらも正常。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

PdhGetFormattedCounterArray は、複数のカウンタの値を取得するんではなく、カウンタ
パスにワイルドカードを含む単一のカウンタハンドルに使うんじゃないんでしょうか。
複数の PdhGetFormattedCounterValue を一つにまとめたような関数じゃなく、カウンタ
パスがワイルドカードを含むかどうかによって、PdhGetFormattedCounterValue と使い分
けるものであって、PdhAddCounter とは1対1に対応するんだと思います。

たぶんね。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

そう推測した理由も書いときますか。

まず、PdhAddCounter の第4引数は、[out] と書かれています。
http://msdn.microsoft.com/en-us/library/aa372204.aspx

ここから、

> PdhAddCounter( hQuery, CountPath[0], 0, &hCounter );
> PdhAddCounter( hQuery, CountPath[1], 0, &hCounter );
> PdhAddCounter( hQuery, CountPath[2], 0, &hCounter );

このような使い方は誤りであることが分かります。
2回目と3回目の呼び出しでは、単に前の値を上書きしているだけで、カウンタを積算す
るようなものではありません。
もし、ひとつのカウンタハンドルで複数のカウンタパスを保持できるなら、第4引数は
[in, out] となっているはずです。

続いて、PdhGetFormattedCounterValue の引数に注目します。
http://msdn.microsoft.com/en-us/library/aa372637.aspx

もしこれが、複数のカウンタハンドルの値を一括取得するものであれば、第1引数が配列
になっているのが普通ですし、単一のカウンタハンドルの値を複数のフォーマットで一括
取得するのであれば、第2引数が配列になっているべきです。
そのどちらでもないことから、1つのカウンタハンドル、1つのフォーマットなのに、結
果が複数あるということになります。

で、どういうことかと解説を見れば、

> Use this function when you want to format the counter values of a counter
> that contains a wildcard character for the instance name.

と書いてあるではありませんか。
「インスタンス名にワイルドカードを含むカウンタの値をフォーマットするのに使いま
す」といったところでしょうか。

まぁ、そういうわけです。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> 続いて、PdhGetFormattedCounterValue の引数に注目します。
> http://msdn.microsoft.com/en-us/library/aa372637.aspx

リンク先間違えました。
こっちです。

http://msdn.microsoft.com/en-us/library/aa372633.aspx


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

aetosまさ。
ご回答ありがとうございます。

> このような使い方は誤りであることが分かります。
確かにこちらも PdhAddCounter の引数に OUT となっているため
カウンタの積算はしないだろうと思いカウンタを配列にしたり
いろいろと試しました。でもすべて失敗しました。

> と書いてあるではありませんか。
> 「インスタンス名にワイルドカードを含むカウンタの値をフォーマットするのに使い

> す」といったところでしょうか。
英語サイトの記述を見逃していました。

カウンタ・パスに『\LogicalDisk(*/*#*)\*』に変更して試してみました。

// 一括取得(またも異常)
VOID GetMemoryInfo3( LPCTSTR lpCountPath )
{
PDH_HQUERY hQuery;
PDH_HCOUNTER hCounter;
PDH_FMT_COUNTERVALUE_ITEM fmtArray[ 1024 ] = { 0 };
DWORD dwArray = sizeof(fmtArray);
DWORD dwCount;

if ( PdhOpenQuery(NULL,0,&hQuery) == ERROR_SUCCESS ){
PdhAddCounter( hQuery, lpCountPath, 0, &hCounter );
PdhCollectQueryData( hQuery );
DispError( PdhGetFormattedCounterArray
(hCounter,PDH_FMT_LONG,&dwArray,&dwCount,fmtArray) );
PdhCloseQuery( hQuery );
for ( DWORD i = 0 ; i < dwCount ; i++ ){
printf( %-30s = %10ld B\n,
fmtArray[i].szName,
fmtArray[i].FmtValue.longValue );
}
printf( dwCount = %lu 個\n, dwCount );
printf( dwArray = %lu 個\n, dwArray );
printf( \n );
}
}
結果は
PdhGetFormattedCounterArray が PDH_CSTATUS_ITEM_NOT_VALIDATED を
返してみました。
これエラーです。

こんどは何がいけないのですかね?


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

> そう推測した理由も書いときますか。
僕は最初 2ch の情報を参考にしました。

http://ir9.jp/prog/ayu/datlog/tech_win32api/1017072275/1017072275_01.html
ここの 188、189 です。

> 188
> パフォーマンスモニタから値の取得について...
>
> AddCounterでカウンタを複数追加した場合に、
> 追加したカウンタに対応するデータを纏めて取得する方法を知りませんか?
> ご存知の方、よろしくお願いします。m(_ _)m

> 189
> ふぅ,やっと取れた。PdhGetFormattedCounterArrayって関数で。
> MSDNのヘルプを信じたウチが悪いのか?
となってみました。
このため PdhGetFormattedCounterArray でまとめて取得可能かと思いました。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

いくらなんでもカウンタパスがそれじゃ大雑把すぎる気が…
PdhAddCounter は成功しているんですか?


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

aetos さまへ。

> PdhAddCounter は成功しているんですか?
はい。
戻り値は正常でした。

> いくらなんでもカウンタパスがそれじゃ大雑把すぎる気が…
どんなカウンタ・パスなら成功するのでしょうか?
こちらも色々と試してみたのですが。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

http://msdn.microsoft.com/en-us/library/aa373193.aspx

省略できるのは、インスタンス名だけだと思います。

例えば、メモ帳の仮想メモリ使用量を調べる場合、

\Process(notepad#0)\Virtual Bytes

のようになりますが、さすがにオブジェクト名(Process)とカウンタ名(Virtual
Bytes)は省略できないだろうと思います。
\Process(*)\Virtual Bytes とすれば、メモ帳以外も含むすべてのプロセスの仮想メモ
リ使用量が取得できますが、メモ帳だけにしようと思って \Process(notepad#*)
\Virtual Bytes としてもダメでした。
parent ってのはどんな時に使うのかよくわかりません。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

書き忘れ。

Memory オブジェクトにはインスタンスの概念がないので、ワイルドカードは使えないで
しょうね。


返信引用
オレンジフィッシュ
 オレンジフィッシュ
(@オレンジフィッシュ)
ゲスト
結合: 18年前
投稿: 58
Topic starter  

aetos さま。
書き込み遅れました。

>Memory オブジェクトにはインスタンスの概念がないので、ワイルドカードは使えない

最初はこれで失敗しました。

>省略できるのは、インスタンス名だけだと思います。
ありがとうございました。
メモリは地道に一個ずつ PdhGetFormattedCounterValue で取得します。

> parent ってのはどんな時に使うのかよくわかりません。
parent は[Thread]オブジェクトの場合にプロセスの名前を指定するときに使うようで
す。
http://eternalwindows.jp/windevelop/pdh/pdh04.html
上から5番目に書かれている。

すべて解決しました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました