CPU, RAM, 네트워크, 하드디스크, 배터리 사용량 정보 구하는 코드

예전에 뭐땜시인지는 기억나지 않는데 CPU에 얼마나 여유가 있는지 확인하는 코드가 필요한적이 있었다.

그때 그 이유로 인터넷에서 여기저기 뒤쳐서 찾아놓은 샘플예제가 있었는데 지금 살펴보니 딱히 보기 좋은 상태가 아니라서(주석도 없고) 그냥 버리기엔 아깝고 해서 코드를 내 취향에 맞게 여기 정리해둠.

#include "SystemStatus.h"
#include <string>
#include <tchar.h>
 
CSystemStatus::CSystemStatus(void)
:m_hQuery(NULL),m_hCounterCPUTotal(NULL), m_CPUCoreCount(0), m_phCounterCPUCore(nullptr),m_NetAdaptorCount(0)
{
	
}

CSystemStatus::~CSystemStatus(void)
{
}

void
CSystemStatus::Init()
{
	PdhOpenQuery(NULL, 0, &m_hQuery);

	//CPU Total
	PdhAddCounter( m_hQuery, TEXT("\Processor(_Total)\% Processor Time"), 1, &m_hCounterCPUTotal );

	// CPU core 정보
	SYSTEM_INFO SystemInfo = { 0 };
	GetSystemInfo(&SystemInfo);
	if (SystemInfo.dwNumberOfProcessors > 0){
		m_CPUCoreCount = SystemInfo.dwNumberOfProcessors;
		m_phCounterCPUCore = new HCOUNTER[m_CPUCoreCount];
		for (int cnt = 0; cnt < m_CPUCoreCount; cnt++){
			TCHAR szFullCounterPath[1024] = { 0 };
			wsprintf(szFullCounterPath, TEXT("\Processor(%d)\%% Processor Time"), cnt);
			PdhAddCounter(m_hQuery, szFullCounterPath, 1, &m_phCounterCPUCore[cnt]);
		}
	}
	
	// 네트워크 카드
	DWORD pcchCounterListLength = 0, pcchInstanceListLength = 0 ;
	PdhEnumObjectItems( NULL, NULL, TEXT("Network Interface"), NULL, &pcchCounterListLength, NULL, &pcchInstanceListLength, PERF_DETAIL_WIZARD, 0 );	

	LPTSTR lpCounterList = new TCHAR[pcchCounterListLength];
	m_lpNetAdaptorList = new TCHAR[pcchInstanceListLength];
	if ( lpCounterList && m_lpNetAdaptorList ){
		/*HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPerfliblangid */
		/*
		Bytes Total/sec
		Packets/sec
		Packets Received/sec
		Packets Sent/sec
		Current Bandwidth
		Bytes Received/sec
		Packets Received Unicast/sec
		Packets Received Non-Unicast/sec
		Packets Received Discarded
		Packets Received Errors
		Packets Received Unknown
		Bytes Sent/sec
		Packets Sent Unicast/sec
		Packets Sent Non-Unicast/sec
		Packets Outbound Discarded
		Packets Outbound Errors
		Output Queue Length
		Offloaded Connections
		TCP Active RSC Connections
		TCP RSC Coalesced Packets/sec
		TCP RSC Exceptions/sec
		TCP RSC Average Packet Size	*/
		
		PdhEnumObjectItems( NULL, NULL, TEXT("Network Interface"), lpCounterList, &pcchCounterListLength, m_lpNetAdaptorList, &pcchInstanceListLength, PERF_DETAIL_WIZARD, 0 );		

		TCHAR* pList = m_lpNetAdaptorList;
		m_NetAdaptorCount = 0;	//어댑터 갯수
		while (*pList) {
			m_NetAdaptorCount++;
			pList += (1 + _tcslen(pList));
		}

		m_phCounterNetAdaptor = new HCOUNTER[m_NetAdaptorCount];
		memset(m_phCounterNetAdaptor, 0, sizeof(HCOUNTER)*m_NetAdaptorCount);
		
		TCHAR* szInstanceName = m_lpNetAdaptorList;
		for (size_t cnt = 0; cnt < m_NetAdaptorCount; cnt++) {
			TCHAR szFullCounterPath[1024] = { 0 };
			DWORD dwFullPathSize = 1024;

			PDH_COUNTER_PATH_ELEMENTS pcpe = { 0 };
			pcpe.szObjectName = TEXT("Network Interface");
			pcpe.szInstanceName = szInstanceName;
			pcpe.dwInstanceIndex = -1;
			pcpe.szCounterName = TEXT("Bytes Total/sec");
			PdhMakeCounterPath(&pcpe, szFullCounterPath, &dwFullPathSize, 0);
			PdhAddCounter(m_hQuery, szFullCounterPath, 1, &m_phCounterNetAdaptor[cnt]);

			szInstanceName += (1 + _tcslen(szInstanceName));
		}
		delete lpCounterList;
	} 
}

void
CSystemStatus::getCPUStatus(LONG &total, LONG* arrCore, size_t arrCoreSize) {
	PDH_FMT_COUNTERVALUE PFC_Value = { 0 };
	PdhGetFormattedCounterValue(m_hCounterCPUTotal, PDH_FMT_LONG, NULL, &PFC_Value);
	total = PFC_Value.longValue;

	if (arrCore != nullptr && arrCoreSize > 0) {
		for (size_t c1 = 0; c1 < arrCoreSize; c1++){
			PDH_FMT_COUNTERVALUE PFC_Value = { 0 };
			PdhGetFormattedCounterValue(m_phCounterCPUCore[c1], PDH_FMT_LONG, NULL, &PFC_Value);
			arrCore[c1] = PFC_Value.longValue;
		}
	}
}

void
CSystemStatus::getRAMStatus(int &availableMem, int &physicalMem) {
	//메모리값
	MEMORYSTATUSEX MemoryStatus = {0};
	MemoryStatus.dwLength = sizeof (MemoryStatus);
	::GlobalMemoryStatusEx(&MemoryStatus);
	
	availableMem = (int)((MemoryStatus.ullTotalPhys - MemoryStatus.ullAvailPhys)/(1024*1024));
	physicalMem =  (int)((MemoryStatus.ullTotalPhys)/(1024*1024));
}

void
CSystemStatus::getNETStatus(LONG *adapTotalByte, size_t adaptorCount) {
	////네트워크
	PDH_FMT_COUNTERVALUE PFC_Value = { 0 };

	for (int cnt = 0; cnt < adaptorCount; cnt++) {
		PdhGetFormattedCounterValue(m_phCounterNetAdaptor[cnt], PDH_FMT_LONG, NULL, &PFC_Value);
		adapTotalByte[cnt] = PFC_Value.longValue;
	}
}

void
CSystemStatus::Update(){
	// 카운트 갱신
	PdhCollectQueryData( m_hQuery );
}

void
CSystemStatus::Terminate(){

	PdhRemoveCounter(m_hCounterCPUTotal);
	
	for (int cnt = 0; cnt < m_CPUCoreCount; cnt++)
		PdhRemoveCounter(m_phCounterCPUCore[cnt]);
	delete(m_phCounterCPUCore);

	for (int cnt = 0; cnt < m_NetAdaptorCount; cnt++)
		PdhRemoveCounter(m_phCounterNetAdaptor[cnt]);
	delete[] m_phCounterNetAdaptor;

	delete[] m_lpNetAdaptorList;
}

SystemStatus.cpp

#include <pdh.h>
#include <pdhmsg.h>
#include <Iphlpapi.h>
#pragma comment(lib, "pdh.lib")
#pragma comment(lib, "Iphlpapi.lib")

class CSystemStatus{
private:
		HQUERY					m_hQuery;

		size_t					m_CPUCoreCount;
		HCOUNTER				m_hCounterCPUTotal;	
		HCOUNTER*				m_phCounterCPUCore;		

		size_t					m_NetAdaptorCount;		//어댑터 갯수
		LPTSTR					m_lpNetAdaptorList;		//어댑터 이름 리스트
		HCOUNTER*				m_phCounterNetAdaptor;
		
public:
	CSystemStatus();
	~CSystemStatus(void);

	void	Init();
	void	Update();
	void	Terminate();
	
	size_t	getCPUCount() {	return m_CPUCoreCount;}
	void	getCPUStatus(LONG &total, LONG* arrCore, size_t arrCoreSize );
	void	getRAMStatus(int &availableMem, int &physicalMem); //단위:MB

	size_t			getNetAdaptorCount() { return m_NetAdaptorCount; }
	const LPTSTR	getNetAdatorList() { return m_lpNetAdaptorList;}
	void			getNETStatus(LONG *adapTotalByte, size_t adaptorCount);  

 };

SystemStatus.h

간단하게 설명하면 프로그램 실행시 Init(); 한번 실행해주고 프로그램 종료시에 Terminate(); 실행해주면 된다. 그리고 값 가져오기 전에 Update(); 한번 실행해주고 필요한 값 가져오면 됨.

다른것들에 대한걸 가져오고 싶으면 저 PdhAddCounter() 함수에 대해 여기저기 검색해보면 나옴.


//배터리 관련 정보
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa373232(v=vs.85).aspx
SYSTEM_POWER_STATUS power_status = { 0 };
if (GetSystemPowerStatus(&power_status)) {

	if (power_status.BatteryFlag != 128) { //128 == No system battery
		if (power_status.ACLineStatus == 1)
			tmpLog.Format(TEXT("전원 연결중rn"));
		else
			tmpLog.Format(TEXT("배터리 사용중rn"));
		m_strEditOutput += tmpLog;

		tmpLog.Format(TEXT("배터리 충전률: %d%%rn"), power_status.BatteryLifePercent);
		m_strEditOutput += tmpLog;

		if (power_status.BatteryLifeTime != -1){
			int min = power_status.BatteryLifeTime / 60;
			if (min > 60)
				tmpLog.Format(TEXT("남은시간: %d시간 %d분rn"), min / 60, min % 60);
			else
				tmpLog.Format(TEXT("남은시간: %d분rn"), min);
		}
		else
			tmpLog.Format(TEXT("남은시간 계산중...rn"));
		m_strEditOutput += tmpLog;
	}
	else {
		tmpLog.Format(TEXT("No Batteryrn"));
		m_strEditOutput += tmpLog;
	}
}

배터리 관련 정보 구하는 코드


//하드디스크 
DWORD dwDrive = GetLogicalDrives();
DWORD dwDriveCh = 0x0001;
TCHAR DriveText[3] = { 0 };

for (TCHAR Drive = 'A'; Drive <= 'Z'; Drive++){
	wsprintf(DriveText, TEXT("%C:"), Drive);
	UINT type = GetDriveType(DriveText);
	if ((dwDrive & dwDriveCh) && (type == DRIVE_REMOVABLE || type == DRIVE_FIXED || type == DRIVE_RAMDISK)){
		// 하드용량			
		ULARGE_INTEGER i64FreeBytesToCaller = { 0 }, i64TotalBytes = { 0 }, i64FreeBytes = { 0 };
		BOOL bRsult = GetDiskFreeSpaceEx(DriveText, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes, (PULARGE_INTEGER)&i64FreeBytes);
		if (bRsult){
			float ra = 1.0f - (float)(int)(i64FreeBytes.QuadPart >> 20) / (float)(int)(i64TotalBytes.QuadPart >> 20);
			tmpLog.Format(TEXT("%c: %I64d MB / %I64d MB(%d%%)rn"), Drive, i64FreeBytes.QuadPart >> 20, i64TotalBytes.QuadPart >> 20, (int)(ra * 100));
			m_strEditOutput += tmpLog;
		}
	}
	dwDriveCh <<= 1;
}

하드디스크 정보 구하는 코드


Comments

“CPU, RAM, 네트워크, 하드디스크, 배터리 사용량 정보 구하는 코드”에 대한 4개의 응답

  1. 혹시 프로젝트는 mfc 프로젝트로 생성하고 edit Control하나를 만들어주고 변수 이름을 m_strEditOutput로 설정하신게 맞나욤?

    1. 네 맞습니다 맨위에 스샷에 결과 나오는 에디트박스가 m_strEditOutput랑 연결되어있습니다.

  2. 좋네여

    1. 감사합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다