// 磁盤.cpp: 定義控制臺應用程式的入口點。會出現一個錯誤,就是PDH_NO_DATA from PDHCOLLECTQUERYDATA,有人說是 wrong instance ,我也不知道哪里錯了,求問各位
//
#include "stdafx.h"
#pragma comment(lib,"pdh")
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <locale.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <tchar.h>
#include <windows.h>
int nCPU;
int GetData()
{
HQUERY query;
double dbVal;
long iVal;
PDH_STATUS status = PdhOpenQuery(NULL, NULL, &query);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("打開失敗"), TEXT(""), MB_OK);
return -1;
}
HCOUNTER cntProcessCPU, cntProcessMemory;
HCOUNTER cntProcessDiskRead, cntProcessDiskWrite;
status = PdhAddCounterA(query, "\\Process(tfb_manage_system)\\% Processor Time", NULL, &cntProcessCPU);
status = PdhAddCounterA(query, "\\Process(tfb_manage_system)\\Working Set - Private", NULL, &cntProcessMemory);
status = PdhAddCounterA(query, "\\Process(tfb_manage_system)\\IO Read Bytes/sec", NULL, &cntProcessDiskRead);
status = PdhAddCounterA(query, "\\Process(tfb_manage_system)\\IO Write Bytes/sec", NULL, &cntProcessDiskWrite);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("添加失敗"), TEXT(""), MB_OK);
return -1;
}
status = PdhCollectQueryData(query);
Sleep(500); //這里要有延時不然結果相當不準確
status = PdhCollectQueryData(query);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("資料請求失敗"), TEXT(""), MB_OK);
return -1;
}
printf("=====");
PDH_FMT_COUNTERVALUE pdhValue;
DWORD dwValue;
status = PdhGetFormattedCounterValue(cntProcessCPU, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("得到資料失敗"), TEXT(""), MB_OK);
return -1;
}
else
{
dbVal = pdhValue.doubleValue;
printf("Process-CPU: %3d%% ", (int)(dbVal / nCPU + 0.5));
}
status = PdhGetFormattedCounterValue(cntProcessMemory, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("得到資料失敗"), TEXT(""), MB_OK);
return -1;
}
else
{
dbVal = pdhValue.doubleValue;
printf("Process-Memory: %8dK \n", (int)(dbVal / 1024));
}
status = PdhGetFormattedCounterValue(cntProcessDiskRead, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("得到資料失敗"), TEXT(""), MB_OK);
return -1;
}
else
{
dbVal = pdhValue.doubleValue;
printf("Process-DiskRead:%8dK/s ", (int)(dbVal / 1024));
}
status = PdhGetFormattedCounterValue(cntProcessDiskWrite, PDH_FMT_DOUBLE, &dwValue, &pdhValue);
if (ERROR_SUCCESS != status)
{
MessageBox(NULL, TEXT("得到資料失敗"), TEXT(""), MB_OK);
return -1;
}
else
{
dbVal = pdhValue.doubleValue;
printf("Process-DiskWrite:%8dK/s \n*****************************************************************************\n", (int)(dbVal / 1024));
}
PdhRemoveCounter(cntProcessCPU);
PdhRemoveCounter(cntProcessMemory);
PdhRemoveCounter(cntProcessDiskRead);
PdhRemoveCounter(cntProcessDiskWrite);
PdhCloseQuery(query);
}
int main() {
setlocale(LC_ALL, "chs");
SYSTEM_INFO si;
GetSystemInfo(&si);
nCPU = si.dwNumberOfProcessors;
while (1)
{
Sleep(500);
GetData();
}
system("pause");
return 0;
}
uj5u.com熱心網友回復:
是編譯錯誤還是運行中間錯誤如果是運行錯誤,執行到哪里出錯?
uj5u.com熱心網友回復:
僅供參考:#pragma comment(lib,"pdh")
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <locale.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <tchar.h>
#include <windows.h>
//一.性能計數器簡介:
//系統性能計數器?也許好多朋友沒有用過吧!(獻丑了)此物可謂功能強大,顧名思義就是可以統計 Windows 系統各項性能指標的東西。在 Windows 2000 及以上系統中,如果是默認安裝就會自帶性能計數器程式,大家可以在 “控制面板 -〉管理 -〉性能”中看到該程式。
//Windows 系統性能計數器可以實時跟蹤上百項系統性能指標,在該系統程式的繪圖界面上滑鼠右擊,選擇“添加計數器”就有可能看到所有可統計的專案。常常在論壇里看到一些新朋友問如何自己實作任務管理器,及如何實時獲得每個行程的CPU使用率,記憶體使用...等等,那么我想使用系統性能計數器應該是最佳選擇。言歸正傳,實作方法,請看下文。
//二.具體實作:
//相關API簡介及事例代碼:
bool pdhdump() {
//1.PdhOpenQuery:打開計數器
PDH_STATUS pdhStatus;
// HQUERY hQuery = NULL;
// HCOUNTER pCounterHandle = NULL;
// pdhStatus = PdhOpenQuery(0, 0, &hQuery);
// if (pdhStatus != ERROR_SUCCESS) return false;
// //分配計數器句柄空間
// pCounterHandle = (HCOUNTER *)GlobalAlloc(GPTR, sizeof(HCOUNTER));
// if (pCounterHandle == NULL) return false;
//2.PdhCloseQuery:關閉計數器
// pdhStatus = PdhCloseQuery(hQuery);
// 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 lpcsMachineName= NULL;
LPTSTR lpsObjectListBuffer = 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;
//保存緩沖區地址
LPTSTR lpsthisObject = NULL;
lpsthisObject = lpsObjectListBuffer;
//列印所有可用計數專案
if (dwObjectListSize>0)
for ( ; *lpsthisObject != 0 ; lpsthisObject += (strlen(lpsthisObject) + 1)) {
printf("Object:%s\n",lpsthisObject);
//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 // 0
// );
//舉例:該函式的方法同上一函式(PdhEnumObjects),具體請看MSDN或本文附帶的測驗工程代碼
LPTSTR mszCounterList=NULL;
LPTSTR mszInstanceList=NULL;
DWORD dwCounterListLength=0;
DWORD dwInstanceListLength=0;
//第一步先把緩沖去大小置為0,這樣可獲得所需緩沖區大小
pdhStatus = PdhEnumObjectItems(
NULL,
lpcsMachineName,
lpsthisObject,
mszCounterList,
&dwCounterListLength,
mszInstanceList,
&dwInstanceListLength,
PERF_DETAIL_WIZARD,
0);
if (pdhStatus != ERROR_SUCCESS && pdhStatus != PDH_MORE_DATA) return false;
//得到緩沖區大小后,分配快取區記憶體
mszCounterList = (LPTSTR)malloc(dwCounterListLength + 1);
if (mszCounterList== NULL) return false;
mszInstanceList= (LPTSTR)malloc(dwInstanceListLength+ 1);
if (mszInstanceList== NULL) return false;
pdhStatus = PdhEnumObjectItems(
NULL,
lpcsMachineName,
lpsthisObject,
mszCounterList,
&dwCounterListLength,
mszInstanceList,
&dwInstanceListLength,
PERF_DETAIL_WIZARD,
0);
if (pdhStatus != ERROR_SUCCESS) return false;
LPTSTR lpsthisCounter = NULL;
lpsthisCounter = mszCounterList;
if (dwCounterListLength>0)
for ( ; *lpsthisCounter != 0 ; lpsthisCounter += (strlen(lpsthisCounter) + 1)) {
printf(" Counter:%s\n",lpsthisCounter);
}
LPTSTR lpsthisInstance = NULL;
lpsthisInstance = mszInstanceList;
if (dwInstanceListLength>0)
for ( ; *lpsthisInstance != 0 ; lpsthisInstance += (strlen(lpsthisInstance) + 1)) {
printf(" Instance:%s\n",lpsthisInstance);
}
free(mszInstanceList);
free(mszCounterList);
}
free(lpsObjectListBuffer);
return true;
}
//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 (hQuery, "//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(hQuery);
// 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(hQuery);
// if (pdhStatus != ERROR_SUCCESS)return false;
//提示:pCounterHandle為PdhAddCounter得到的句柄,可以不同的pCounterHandle獲得不同計數值
//8.PdhRemoveCounter:移出計數器
//不想獲取某項計數值時,應該移出該計數器,已節省資源
//舉例:
// if (PdhRemoveCounter(pdhCouner) != ERROR_SUCCESS) return false;
//該函式引數為計數器句柄
//至此,如果使用計數器實時跟蹤系統資訊已經講解完畢。如還有不明白的朋友請詳細察看MSDN或與Email:[email protected] 或 QQ:8573980聯系。
//三.最后再附帶介紹一個相關API PdhGetCounterInfo,這個API與使用計數器并無關系,但是,它可以讓你明白你所感興趣的計數器的路徑。既它可以得到每個計數器的專案的描述資訊(可是中文的哦!)
//舉例:
// //以獲取系統自啟動到現在所運行的秒數為例
// PDH_COUNTER_INFO pdhCounterInfo;
// DWORD dwCounterBuffsize;
// //添加計數器
// pdhStatus = PdhAddCounter(hQuery, "//System//System 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 指計算機自上次啟動后已經運行的時間(用秒計算)。這個計數值顯示啟動時間和當前時間之差。"
//全部介紹完畢,希望本文能對大家有所幫助,祝大家愉快。
//example code:
int ExistSameName(TCHAR *ProcessName) {
//TODO:判斷當前行程串列中有沒有同名行程,如果有回傳第幾個同名行程
return 0;
}
char *RenameEx(char *tmp,int num) {
//TODO:在tmp中的字串末尾添加#num
return tmp;
}
int GetCPUUsage(TCHAR *ProcessName) {
HQUERY hQuery;
HCOUNTER *pCounterHandle;
PDH_STATUS pdhStatus;
PDH_FMT_COUNTERVALUE fmtValue;
DWORD ctrType;
CHAR szPathBuffer[MAX_PATH];
int RetVal = 0;
pdhStatus = PdhOpenQuery(NULL, 0, &hQuery);//打開查詢物件
pCounterHandle = (HCOUNTER *)GlobalAlloc(GPTR, sizeof(HCOUNTER));
//合成查詢字串
char *process = NULL; //處理之后的行程計數器名
if (strstr(ProcessName,".exe") || strstr(ProcessName,".EXE")) {
//如果是以exe結尾,去掉后綴名
int len = strlen(ProcessName) - 4;
char * tmp =new char [len + 6];//為后面#num留出空間
memcpy(tmp , ProcessName, len);
tmp[len] = 0;
process = tmp;
int num = ExistSameName(ProcessName); //需要計數
if (num) {//重名
//如果有同名行程,當前計數器名字改為 "ProcessName#num"
//如 MSDEV.EXE,則有 MSDEV,MSDEV#1,MSDEV#2
process = RenameEx(tmp, num);
}
} else if (strcmpi(ProcessName, "System Idle Process")) {
//如果是系統空閑行程,可指定計數器名字為Idle
int len = strlen("Idle");
char * tmp = new char[len + 1];
strncpy(tmp, "Idle", len);
tmp[len] = 0;
process = tmp;
} else {
//名為System的行程
process = ProcessName;
}
sprintf(szPathBuffer,"//Process(%s)//%% Processor Time", process);
pdhStatus = PdhAddCounter(hQuery, szPathBuffer , 0 , pCounterHandle);
pdhStatus = PdhCollectQueryData(hQuery);
pdhStatus = PdhGetFormattedCounterValue (//獲取計數器當前值
*pCounterHandle,//計數器句柄
PDH_FMT_LONG | PDH_FMT_NOSCALE, //format格式
&ctrType, //控制型別
&fmtValue); //回傳值
if (pdhStatus == ERROR_SUCCESS) {
//fmtValue.doubleValue為所要的結果
RetVal = fmtValue.longValue;// [type: double,long,string,large]
} else {
RetVal = 0;
}
pdhStatus = PdhCloseQuery(hQuery);//關閉查詢句柄
return RetVal;
}
int main() {
setlocale(LC_ALL,"chs");
pdhdump();
return 0;
}
uj5u.com熱心網友回復:
Debug下自己單步執行一下看看,找到出錯的代碼先~uj5u.com熱心網友回復:
就是運行中錯誤,運行后一直彈出“資料請求失敗”,應該就是status = PdhCollectQueryData(query);這個出錯了,但是不知道怎么修改uj5u.com熱心網友回復:
一個是是否管理員權限運行,另一個就是你引數是不是對
uj5u.com熱心網友回復:
PdhCollectQueryDataThe PdhCollectQueryData function collects the current raw data value for all counters in the specified query and updates the status code of each counter.
PDH_STATUS PdhCollectQueryData(
IN HQUERY hQuery // handle of the query
);
Parameters
hQuery
The handle of the query from which to collect data.
Return Values
If the function succeeds, it returns ERROR_SUCCESS.
If the function fails, the return value is a PDH error status defined in pdhmsg.h. The following are possible error values:
Value Meaning
PDH_INVALID_HANDLE The query handle is not valid.
PDH_NO_DATA The query does not currently have any counters.
Remarks
The PdhCollectQueryData function can succeed, but may not have collected data for all counters. Always check the status code of each counter in the query before using the data.
See Also
Performance Data Helper Overview, Performance Data Functions, , PdhOpenQuery
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/79640.html
標籤:硬件/系統
