系統效能計數器[Z]
FROM:http://hi.baidu.com/wlzqi/blog/item/d9782e73f4b4ba1c8701b092.html
上面的地址是專家的地址,有什麼問題請那邊看
一.效能計數器簡介:
系統效能計數器?也許好多朋友沒有用過吧!(獻醜了)此物可謂功能強大,顧名思義就是可以統計 Windows 系統各項效能指標的東西。在 Windows 2000 及以上系統中,如果是預設安裝就會內建效能計數器程式,大家可以在 “控制台 -〉管理 -〉效能”中看到該程式。
Windows 系統效能計數器可以即時跟蹤上百項系統效能指標,在該系統程式的繪圖介面上滑鼠右擊,選擇“添加計數器”就有可能看到所有可統計的項目。常常在論壇裡看到一些新朋友問如何自己實現 工作管理員 ,及如何即時獲得每個進程的CPU使用率,記憶體使用量...等等,那麼我想使用系統效能計數器應該是最佳選擇。言歸正傳,實現方法,請看下文。
二.具體實現:
相關API簡介及案例代碼:
1.PdhOpenQuery:開啟計數器
PDH_STATUS pdhStatus;
HQUERY phQuery = NULL;
HCOUNTER pCounterHandle = NULL;
pdhStatus = PdhOpenQuery(0, 0, &phQuery);
if (pdhStatus != ERROR_SUCCESS) return false;
// 分配計數器控制代碼空間
pCounterHandle = (HCOUNTER *)GlobalAlloc(GPTR, sizeof(HCOUNTER));
if (pCounterHandle == NULL) return false;
2.PdhCloseQuery:關閉計數器
pdhStatus = PdhCloseQuery(phQuery);
if (pdhStatus != ERROR_SUCCESS) return false;
3.PdhEnumObjects:枚舉計數項目,該函數有6個參數(詳細請看MSDN)
原型:
PDH_STATUS PdhEnumObjects(
LPCTSTR szDataSource, // 必須為 NULL
LPCTSTR szMachineName, // 機器名,如果為本機可以為NULL
LPTSTR mszObjectList, // 接收全部可用計數項目的緩衝區
LPDWORD pcchBufferLength, // 緩衝去大小(如果為 0,則該值返回所需大小)
DWORD dwDetailLevel, // 擷取資訊的層級
BOOL bRefresh // 一般設定為 TRUE
);
舉例:
LPTSTR lpsObjectListBuffer = NULL;
LPTSTR lpsthisObject = NULL;
DWORD dwObjectListSize = 0;
// 第一步先把緩衝去大小置為0,這樣可獲得所需緩衝區大小
pdhStatus = PdhEnumObjects (
NULL,
lpcsMachineName,
lpsObjectListBuffer,
&dwObjectListSize,
PERF_DETAIL_WIZARD,
TRUE);
if (pdhStatus != ERROR_SUCCESS || pdhStatus != PDH_MORE_DATA) return false;
// 得到緩衝區大小後,分配緩衝區記憶體
lpsObjectListBuffer = (LPTSTR)malloc(dwObjectListSize + 1);
if (lpsObjectListBuffer == NULL) return false;
// 第二步在此調用枚舉函數真正開始枚舉計數項目
pdhStatus = PdhEnumObjects (
NULL,
lpcsMachineName,
lpsObjectListBuffer,
&dwObjectListSize,
PERF_DETAIL_WIZARD,
TRUE);
if (pdhStatus != ERROR_SUCCESS) return false;
// 儲存緩衝區地址
lpsthisObject = lpsObjectListBuffer;
// 列印所有可用計數項目
for ( ; *lpsthisObject != 0 ; lpsthisObject += (lstrlen(lpsthisObject) + 1))
{
printf(lpsthisObject);
}
if (lpsObjectListBuffer)
{
free (lpsObjectListBuffer);
lpsObjectListBuffer = NULL ;
dwObjectListSize = 0;
}
4.PdhEnumObjectItems:枚舉計數器及執行個體
原型:
PDH_STATUS PdhEnumObjectItems(
LPCTSTR szDataSource, // 必須為NULL
LPCTSTR szMachineName, // 機器名,如果為本機可以為NULL
LPCTSTR szObjectName, // 計數項目(通過PdhEnumObjects函數可獲得所有可用項目)
LPTSTR mszCounterList, // 計數器緩衝區
LPDWORD pcchCounterListLength, // 計數器緩衝區大小
LPTSTR mszInstanceList, // 計數執行個體緩衝區
LPDWORD pcchInstanceListLength, // 計數執行個體緩衝區大小
DWORD dwDetailLevel, // 擷取資訊的層級
DWORD dwFlags // 一般設定為 TRUE
);
舉例:該函數的方法同上一函數(PdhEnumObjects),具體請看MSDN或本文附帶的測試工程代碼
5.PdhAddCounter:添加計數器
統計感興趣的系統資訊時,必須先將對應的計數器添加進來
原型:
PDH_STATUS PdhAddCounter(
PDH_HQUERY hQuery, // 為PdhOpenQuery開啟的控制代碼
LPCTSTR szFullCounterPath, // 計數器路徑(最大長度為 PDH_MAX_COUNTER_PATH)
DWORD_PTR dwUserData, // 置為 0
PDH_HCOUNTER* phCounter // 計數器控制代碼空間(本文中在PdhOpenQuery函數後已指派)
);
舉例:
// 已擷取winlogon.exe進程的CPU使用率為例
// 通過枚舉並查看計數項目說明可以知道 process 項目是和進程有關的項目
// 再通過枚舉計數器和案例並查看說明可以知道 process 項目下的% Processor Time計數器是關於進程CPU使率的
// 最後在計數器案例中看到winlogon進程(表明該進程正在運行)
pdhStatus = PdhAddCounter (phQuery, " Processor Time", 0, pCounterHandle);
if (pdhStatus != ERROR_SUCCESS) return false;
提示:有些計數器沒有執行個體,比如:要得到系統自啟動到現在所啟動並執行秒數,那麼該計數項目為System,計數器為System Up Time,計數器執行個體為NULL,這時的計數器路徑為"\System\System Up Time"
6.PdhCollectQueryData: 準備擷取當前資料
舉例:
pdhStatus = PdhCollectQueryData(phQuery);
if (pdhStatus != ERROR_SUCCESS)return false;
7.PdhGetFormattedCounterValue:得到資料
舉例:
pdhStatus = PdhGetFormattedCounterValue (pCounterHandle, PDH_FMT_DOUBLE,
&dwctrType, &fmtValue);
if (pdhStatus != ERROR_SUCCESS) return false;
// PDH_FMT_DOUBLE表示返回double型資料,當然還可以返回int等類型資料,請查MSDN
// 擷取下一時刻資料
pdhStatus = PdhCollectQueryData(phQuery);
if (pdhStatus != ERROR_SUCCESS)return false;
提示:pCounterHandle為PdhAddCounter得到的控制代碼,可以不同的pCounterHandle獲得不同計數值
8.PdhRemoveCounter:移出計數器
不想擷取某項計數值時,應該移出該計數器,已節省資源
舉例:
if (PdhRemoveCounter(pdhCouner) != ERROR_SUCCESS) return false;
該函數參數為計數器控制代碼
至此,如果使用計數器即時跟蹤系統資訊已經講解完畢。如還有不明白的朋友請詳細察看MSDN或與
Email: 或 QQ:8573980聯絡。
三.最後再附帶介紹一個相關API PdhGetCounterInfo,這個API與使用計數器並無關係,但是,它可以讓你明白你所感興趣的計數器的路徑。既它可以得到每個計數器的項目的描述資訊(可是中文的哦!)
舉例:
以擷取系統自啟動到現在所啟動並執行秒數為例
PDH_COUNTER_INFO pdhCounterInfo;
DWORD dwCounterBuffsize;
// 添加計數器
pdhStatus = PdhAddCounter(phQuery, " Up Time", 0, pCounterHandle);
if (pdhStatus != ERROR_SUCCESS) return false;
// 得到緩衝區大小
pdhStatus = PdhGetCounterInfo(*pCounterHandle, TRUE, &dwCounterBuffsize, NULL);
if (pdhStatus != ERROR_SUCCESS || pdhStatus != PDH_MORE_DATA) return false;
// 設定緩衝區
BYTE * byCounterBuff = (BYTE *)malloc(dwCounterBuffsize);
// 擷取資訊
pdhStatus = PdhGetCounterInfo (*pCounterHandle, TRUE, &dwCounterBuffsize, (PPDH_COUNTER_INFO)byCounterBuff);
if (pdhStatus != ERROR_SUCCESS) return false;
pdhCounterInfo = * (PPDH_COUNTER_INFO)byCounterBuff;
// 列印得到的資訊
printf(pdhCounterInfo->szExplainText);
以上列印得資訊類似:"System Up Time 指電腦自上次啟動後已經啟動並執行時間(用秒計算)。這個計數值顯示啟動時間和目前時間之差。"
全部介紹完畢,希望本文能對大家有所協助,祝大家愉快。
在別處找到的一個PDH的一些關鍵定義
#define PDH_CSTATUS_VALID_DATA 0x0
#define PDH_CSTATUS_NEW_DATA 0x1
#define PDH_CSTATUS_NO_MACHINE 0x800007D0
#define PDH_CSTATUS_NO_INSTANCE 0x800007D1
#define PDH_MORE_DATA 0x800007D2
#define PDH_CSTATUS_ITEM_NOT_VALIDATED 0x800007D3
#define PDH_RETRY 0x800007D4
#define PDH_NO_DATA 0x800007D5
#define PDH_CALC_NEGATIVE_DENOMINATOR 0x800007D6
#define PDH_CALC_NEGATIVE_TIMEBASE 0x800007D7
#define PDH_CALC_NEGATIVE_VALUE 0x800007D8
#define PDH_DIALOG_CANCELLED 0x800007D9
#define PDH_CSTATUS_NO_OBJECT 0xC0000BB8
#define PDH_CSTATUS_NO_COUNTER 0xC0000BB9
#define PDH_CSTATUS_INVALID_DATA 0xC0000BBA
#define PDH_MEMORY_ALLOCATION_FAILURE 0xC0000BBB
#define PDH_INVALID_HANDLE 0xC0000BBC
#define PDH_INVALID_ARGUMENT 0xC0000BBD
#define PDH_FUNCTION_NOT_FOUND 0xC0000BBE
#define PDH_CSTATUS_NO_COUNTERNAME 0xC0000BBF
#define PDH_CSTATUS_BAD_COUNTERNAME 0xC0000BC0
#define PDH_INVALID_BUFFER 0xC0000BC1
#define PDH_INSUFFICIENT_BUFFER 0xC0000BC2
#define PDH_CANNOT_CONNECT_MACHINE 0xC0000BC3
#define PDH_INVALID_PATH 0xC0000BC4
#define PDH_INVALID_INSTANCE 0xC0000BC5
#define PDH_INVALID_DATA 0xC0000BC6
#define PDH_NO_DIALOG_DATA 0xC0000BC7
#define PDH_CANNOT_READ_NAME_STRINGS 0xC0000BC8