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

현재 페이지를 로딩중입니다.
만약 페이지 로딩이 끝났는데 본문이 보이지 않는다면
광고차단 플러그인 때문이니 잠시 플러그인을 꺼주시면 감사하겠습니다.

The current page is loading.
If the page loading is over but the text is not visible
This is because of the ad blocking plugin, so please be sure to turn off the plugin for a while.

소스 다운로드 : https://github.com/Linsoo/SystemStatusTest


예전에 뭐땜시인지는 기억나지 않는데 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_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\langid */
		/*
		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("전원 연결중\r\n"));
		else
			tmpLog.Format(TEXT("배터리 사용중\r\n"));
		m_strEditOutput += tmpLog;

		tmpLog.Format(TEXT("배터리 충전률: %d%%\r\n"), 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분\r\n"), min / 60, min % 60);
			else
				tmpLog.Format(TEXT("남은시간: %d분\r\n"), min);
		}
		else
			tmpLog.Format(TEXT("남은시간 계산중...\r\n"));
		m_strEditOutput += tmpLog;
	}
	else {
		tmpLog.Format(TEXT("No Battery\r\n"));
		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%%)\r\n"), Drive, i64FreeBytes.QuadPart >> 20, i64TotalBytes.QuadPart >> 20, (int)(ra * 100));
			m_strEditOutput += tmpLog;
		}
	}
	dwDriveCh <<= 1;
}

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

크리에이티브 커먼즈 라이선스 Linsoo의 저작물인 이 저작물은(는)크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

댓글 남기기

이메일은 공개되지 않습니다.

This site uses Akismet to reduce spam. Learn how your comment data is processed.