下面介紹如何遠程取得 Windows Performance Info
一.性能計數器簡介:
系統性能計數器?也許好多朋友沒有用過吧!(獻丑了)此物可謂功能強大,顧名思義就是可以統計 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, "\\process(winlogon)\\% 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或與
三.最後實例獻上
void Main::main()
{
// http://www7a.biglobe.ne.jp/~lshen/EternalWindows/WinDevelop/PDH/PDH05.Html
// http://nienIE.com/~masapico/api_PdhGetCounterInfo.Html
// http://nienIE.com/~masapico/api_PdhExpandCounterPath.Html
//建立遠程IPC鏈接(你要對方的administrator權獻的用戶)
NETRESOURCE nr;
nr.dwType = RESOURCETYPE_ANY;
nr.lpLocalName = NULL;
nr.lpRemoteName = "\\\\PC211";
nr.lpProvider = NULL;
nr.dwDisplayType = RESOURCEDISPLAYTYPE_DOMAIN; //RESOURCEDISPLAYTYPE_GENERIC;//
nr.dwScope = RESOURCE_CONNECTED;
nr.lpComment = NULL;
DWord dwRet = WNetAddConnection2(&nr,"pc211","pc211",0);
if(ERROR_SUCCESS != dwRet){
printf("WNetAddConnection2 failure : %d \n",dwRet);
return;
}
HQUERY hQuery;
HCOUNTER hCounter[10];
PDH_FMT_COUNTERVALUE FmtValue;
PdhOpenQuery(NULL, 0, &hQuery);
PdhAddCounter(hQuery, "\\\\PC211\\Processor(_Total)\\% Processor Time", 0, &hCounter[0]);
PdhAddCounter(hQuery, "\\Memory\\Available Bytes", 0, &hCounter[1]);
PdhCollectQueryData(hQuery);
for(int i=0; i<10; i++) {
Sleep(1000);
PdhCollectQueryData(hQuery);
PdhGetFormattedCounterValue(hCounter[0], PDH_FMT_DOUBLE, NULL, &FmtValue);
; printf("CPU使用率: %f%%\t", FmtValue.doubleValue);
PdhGetFormattedCounterValue(hCounter[1], PDH_FMT_LONG|PDH_FMT_NOSCALE, NULL, &FmtValue);
printf("MEM使用率: %d\n", FmtValue.longValue);
}
PdhCloseQuery(hQuery);
}
全部介紹完畢,希望本文能對大家有所幫助,祝大家愉快。
不明請來電詢問.QQ:9309696 Email:[email protected]