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

소스 다운로드 : 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:
HQUERYm_hQuery;

size_tm_CPUCoreCount;
HCOUNTERm_hCounterCPUTotal;
HCOUNTER*m_phCounterCPUCore;

size_tm_NetAdaptorCount;//어댑터 갯수
LPTSTRm_lpNetAdaptorList;//어댑터 이름 리스트
HCOUNTER*m_phCounterNetAdaptor;

public:
CSystemStatus();
~CSystemStatus(void);

voidInit();
voidUpdate();
voidTerminate();

size_tgetCPUCount() {return m_CPUCoreCount;}
voidgetCPUStatus(LONG &total, LONG* arrCore, size_t arrCoreSize );
voidgetRAMStatus(int &availableMem, int &physicalMem); //단위:MB

size_tgetNetAdaptorCount() { return m_NetAdaptorCount; }
const LPTSTRgetNetAdatorList() { return m_lpNetAdaptorList;}
voidgetNETStatus(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.