www.pudn.com > bxt.zip > CpuUsage.cpp


#include "stdafx.h" 
#include 	// for CRegKey use 
#include "WinPerf.h" 
#include "CpuUsage.h" 
 
 
#pragma pack(push,8) 
#include "PerfCounters.h" 
#pragma pack(pop) 
 
#define SYSTEM_OBJECT_INDEX					2		// 'System' object 
#define PROCESS_OBJECT_INDEX				230		// 'Process' object 
#define PROCESSOR_OBJECT_INDEX				238		// 'Processor' object 
#define TOTAL_PROCESSOR_TIME_COUNTER_INDEX	240		// '% Total processor time' counter (valid in WinNT under 'System' object) 
#define PROCESSOR_TIME_COUNTER_INDEX		6		// '% processor time' counter (for Win2K/XP) 
 
/////////////////////////////////////////////////////////////////// 
// 
//		GetCpuUsage uses the performance counters to retrieve the 
//		system cpu usage. 
//		The cpu usage counter is of type PERF_100NSEC_TIMER_INV 
//		which as the following calculation: 
// 
//		Element		Value  
//		=======		=========== 
//		X			CounterData  
//		Y			100NsTime  
//		Data Size	8 Bytes 
//		Time base	100Ns 
//		Calculation 100*(1-(X1-X0)/(Y1-Y0))  
// 
//      where the denominator (Y) represents the total elapsed time of the  
//      sample interval and the numerator (X) represents the time during  
//      the interval when the monitored components were inactive. 
// 
// 
//		Note: 
//		==== 
//		On windows NT, cpu usage counter is '% Total processor time' 
//		under 'System' object. However, in Win2K/XP Microsoft moved 
//		that counter to '% processor time' under '_Total' instance 
//		of 'Processor' object. 
//		Read 'INFO: Percent Total Performance Counter Changes on Windows 2000' 
//		Q259390 in MSDN. 
// 
/////////////////////////////////////////////////////////////////// 
 
typedef enum 
{ 
	WINNT,	WIN2K_XP, WIN9X, UNKNOWN 
}PLATFORM; 
 
PLATFORM GetPlatform() 
{ 
	OSVERSIONINFO osvi; 
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
	if (!GetVersionEx(&osvi)) 
		return UNKNOWN; 
	switch (osvi.dwPlatformId) 
	{ 
	case VER_PLATFORM_WIN32_WINDOWS: 
		return WIN9X; 
	case VER_PLATFORM_WIN32_NT: 
		if (osvi.dwMajorVersion == 4) 
			return WINNT; 
		else 
			return WIN2K_XP; 
	} 
	return UNKNOWN; 
} 
 
CCpuUsage::CCpuUsage() 
{ 
	m_bFirstTime = true; 
	m_lnOldValue = 0; 
	memset(&m_OldPerfTime100nSec, 0, sizeof(m_OldPerfTime100nSec)); 
} 
 
CCpuUsage::~CCpuUsage() 
{ 
} 
 
BOOL CCpuUsage::EnablePerformaceCounters(BOOL bEnable) 
{ 
	if (GetPlatform() != WIN2K_XP) 
		return TRUE; 
 
	CRegKey regKey; 
	if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfOS\\Performance") != ERROR_SUCCESS) 
		return FALSE; 
 
	regKey.SetValue(!bEnable, "Disable Performance Counters"); 
	regKey.Close(); 
 
	if (regKey.Open(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\PerfProc\\Performance") != ERROR_SUCCESS) 
		return FALSE; 
 
	regKey.SetValue(!bEnable, "Disable Performance Counters"); 
	regKey.Close(); 
 
	return TRUE; 
} 
 
// 
//	GetCpuUsage returns the system-wide cpu usage. 
//	Since we calculate the cpu usage by two samplings, the first 
//	call to GetCpuUsage() returns 0 and keeps the values for the next 
//	sampling. 
//  Read the comment at the beginning of this file for the formula. 
// 
int CCpuUsage::GetCpuUsage() 
{ 
	static PLATFORM Platform = GetPlatform(); 
 
	if (m_bFirstTime) 
		EnablePerformaceCounters(); 
	 
	// Cpu usage counter is 8 byte length. 
	CPerfCounters PerfCounters; 
	char szInstance[256] = {0}; 
 
//		Note: 
//		==== 
//		On windows NT, cpu usage counter is '% Total processor time' 
//		under 'System' object. However, in Win2K/XP Microsoft moved 
//		that counter to '% processor time' under '_Total' instance 
//		of 'Processor' object. 
//		Read 'INFO: Percent Total Performance Counter Changes on Windows 2000' 
//		Q259390 in MSDN. 
 
	DWORD dwObjectIndex; 
	DWORD dwCpuUsageIndex; 
	switch (Platform) 
	{ 
	case WINNT: 
		dwObjectIndex = SYSTEM_OBJECT_INDEX; 
		dwCpuUsageIndex = TOTAL_PROCESSOR_TIME_COUNTER_INDEX; 
		break; 
	case WIN2K_XP: 
		dwObjectIndex = PROCESSOR_OBJECT_INDEX; 
		dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX; 
		strcpy(szInstance,"_Total"); 
		break; 
	default: 
		return -1; 
	} 
 
	int				CpuUsage = 0; 
	LONGLONG		lnNewValue = 0; 
	PPERF_DATA_BLOCK pPerfData = NULL; 
	LARGE_INTEGER	NewPerfTime100nSec = {0}; 
 
	lnNewValue = PerfCounters.GetCounterValue(&pPerfData, dwObjectIndex, dwCpuUsageIndex, szInstance); 
	NewPerfTime100nSec = pPerfData->PerfTime100nSec; 
 
	if (m_bFirstTime) 
	{ 
		m_bFirstTime = false; 
		m_lnOldValue = lnNewValue; 
		m_OldPerfTime100nSec = NewPerfTime100nSec; 
		return 0; 
	} 
 
	LONGLONG lnValueDelta = lnNewValue - m_lnOldValue; 
	double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart; 
 
	m_lnOldValue = lnNewValue; 
	m_OldPerfTime100nSec = NewPerfTime100nSec; 
 
	double a = (double)lnValueDelta / DeltaPerfTime100nSec; 
 
	double f = (1.0 - a) * 100.0; 
	CpuUsage = (int)(f + 0.5);	// rounding the result 
	if (CpuUsage < 0) 
		return 0; 
	return CpuUsage; 
} 
 
int CCpuUsage::GetCpuUsage(LPCTSTR pProcessName) 
{ 
	static PLATFORM Platform = GetPlatform(); 
	 
	if (m_bFirstTime) 
		EnablePerformaceCounters(); 
 
	// Cpu usage counter is 8 byte length. 
	CPerfCounters PerfCounters; 
	char szInstance[256] = {0}; 
 
 
	DWORD dwObjectIndex = PROCESS_OBJECT_INDEX; 
	DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX; 
	strcpy(szInstance,pProcessName); 
 
	int				CpuUsage = 0; 
	LONGLONG		lnNewValue = 0; 
	PPERF_DATA_BLOCK pPerfData = NULL; 
	LARGE_INTEGER	NewPerfTime100nSec = {0}; 
 
	lnNewValue = PerfCounters.GetCounterValue(&pPerfData, dwObjectIndex, dwCpuUsageIndex, szInstance); 
	NewPerfTime100nSec = pPerfData->PerfTime100nSec; 
 
	if (m_bFirstTime) 
	{ 
		m_bFirstTime = false; 
		m_lnOldValue = lnNewValue; 
		m_OldPerfTime100nSec = NewPerfTime100nSec; 
		return 0; 
	} 
 
	LONGLONG lnValueDelta = lnNewValue - m_lnOldValue; 
	double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart; 
 
	m_lnOldValue = lnNewValue; 
	m_OldPerfTime100nSec = NewPerfTime100nSec; 
 
	double a = (double)lnValueDelta / DeltaPerfTime100nSec; 
 
	CpuUsage = (int) (a*100); 
	if (CpuUsage < 0) 
		return 0; 
	return CpuUsage; 
} 
 
 
int CCpuUsage::GetCpuUsage(DWORD dwProcessID) 
{ 
	static PLATFORM Platform = GetPlatform(); 
	 
	if (m_bFirstTime) 
		EnablePerformaceCounters(); 
 
	// Cpu usage counter is 8 byte length. 
	CPerfCounters PerfCounters; 
 
 
	DWORD dwObjectIndex = PROCESS_OBJECT_INDEX; 
	DWORD dwCpuUsageIndex = PROCESSOR_TIME_COUNTER_INDEX; 
 
	int				CpuUsage = 0; 
	LONGLONG		lnNewValue = 0; 
	PPERF_DATA_BLOCK pPerfData = NULL; 
	LARGE_INTEGER	NewPerfTime100nSec = {0}; 
 
	lnNewValue = PerfCounters.GetCounterValueForProcessID(&pPerfData, dwObjectIndex, dwCpuUsageIndex, dwProcessID); 
	NewPerfTime100nSec = pPerfData->PerfTime100nSec; 
 
	if (m_bFirstTime) 
	{ 
		m_bFirstTime = false; 
		m_lnOldValue = lnNewValue; 
		m_OldPerfTime100nSec = NewPerfTime100nSec; 
		return 0; 
	} 
 
	LONGLONG lnValueDelta = lnNewValue - m_lnOldValue; 
	double DeltaPerfTime100nSec = (double)NewPerfTime100nSec.QuadPart - (double)m_OldPerfTime100nSec.QuadPart; 
 
	m_lnOldValue = lnNewValue; 
	m_OldPerfTime100nSec = NewPerfTime100nSec; 
 
	double a = (double)lnValueDelta / DeltaPerfTime100nSec; 
 
	CpuUsage = (int) (a*100); 
	if (CpuUsage < 0) 
		return 0; 
	return CpuUsage; 
}