最近在学习用C++获取WINDOWS和LINUX 下的系统信息,对其大概方法做了一些总结,希望对新人有一些帮助,话不多说,先来代码。。。。。。。。。。。。。。。。。。。
首先,我针对两个平台定义了一个接口类,即纯虚函数类,其windows 和 linux 的实现类可以实现该类,接口代码如下:
#pragma once
#pragma comment(lib,"Kernel32.lib")
#pragma comment(lib,"Psapi.lib")
#include <Windows.h>
#include <TlHelp32.h>
#include<direct.h>
#include<winternl.h>
#include <Psapi.h>
#include <QMap>
//获取系统信息的接口
class ISysInfo
{
public:
virtual ~ISysInfo(){}
/************************************************************************/
/*函数说明:获取系统CPU当前使用率
/*函数参数:nCpuRate->CPU使用率
/*返回结果:返回结果状态
/*作者时间:Bevis 2014-07-19
/************************************************************************/
virtual bool GetSysCpu(int& nCpuRate) = 0;
/************************************************************************/
/*函数说明:获取系统内存信息
/*函数参数:nMemTotal->内存总共大小,(MB);nMemUsed->内存已使用大小,(MB)
/*返回结果:返回结果状态
/*作者时间:Bevis 2014-07-19
/************************************************************************/
virtual bool GetSysMemory(int& nMemTotal,int& nMemUsed) = 0;
/************************************************************************/
/*函数说明:获取系统磁盘信息
/*函数参数:nDiskTotal->磁盘总共大小,(MB);nDiskUsed->磁盘已使用大小,(MB)
/*返回结果:返回结果状态
/*作者时间:Bevis 2014-07-19
/************************************************************************/
virtual bool GetSysDisk(int& nDiskTotal,int& nDiskUsed) = 0;
/************************************************************************/
/*函数说明:遍历系统所有进程
/*函数参数:无
/*返回结果:进程PID和进程名称的映射集合
/*作者时间:Bevis 2014-07-19
/************************************************************************/
virtual QMap<int,QString> GetAllProcess() = 0;
/************************************************************************/
/*函数说明:获取单个进程的内存使用率
/*函数参数:nPid->进程唯一标识号;nProcessMemRate->进程的内存使用率
/*返回结果:返回结果状态
/*作者时间:Bevis 2014-07-19
/************************************************************************/
virtual bool GetProcessMemory(int nPid,int& nProcessMemRate) = 0;
};
由于时间有限,暂时只实现了WINDOWS平台,后续我会补上LINUX的实现....



windows的实现类头文件定义如下:
#pragma once
#include <QDebug>
#include <QString>
#include "ISysInfo.h"
#include <atlconv.h>
#include <string.h>
//在WINDOWS平台上实现
class ISysWin: public ISysInfo
{
public:
ISysWin(void);
virtual ~ISysWin(void);
bool GetSysCpu(int& nCpuRate) ;
bool GetSysMemory(int& nMemTotal,int& nMemUsed);
bool GetSysDisk(int& nDiskTotal,int& nDiskUsed) ;
QMap<int,QString> GetAllProcess() ;
bool GetProcessMemory(int nPid,int& nProcessMemRate) ;
protected:
//时间转换
__int64 Filetime2Int64(const FILETIME* ftime);
//两个时间相减运算
__int64 CompareFileTime(FILETIME preTime,FILETIME nowTime);
};
windows的实现类cpp文件定义如下:
#include "ISysWin.h"
ISysWin::ISysWin(void)
{
}
ISysWin::~ISysWin(void)
{
}
__int64 ISysWin::Filetime2Int64(const FILETIME* ftime)
{
LARGE_INTEGER li;
li.LowPart = ftime->dwLowDateTime;
li.HighPart = ftime->dwHighDateTime;
return li.QuadPart;
}
__int64 ISysWin::CompareFileTime(FILETIME preTime,FILETIME nowTime)
{
return this->Filetime2Int64(&nowTime) - this->Filetime2Int64(&preTime);
}
//将单字节char*转化为宽字节wchar_t*
wchar_t* AnsiToUnicode( const char* szStr )
{
int nLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, NULL, 0 );
if (nLen == 0)
{
return NULL;
}
wchar_t* pResult = new wchar_t[nLen];
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, pResult, nLen );
return pResult;
}
//将宽字节wchar_t*转化为单字节char*
inline char* UnicodeToAnsi( const wchar_t* szStr )
{
int nLen = WideCharToMultiByte( CP_ACP, 0, szStr, -1, NULL, 0, NULL, NULL );
if (nLen == 0)
{
return NULL;
}
char* pResult = new char[nLen];
WideCharToMultiByte( CP_ACP, 0, szStr, -1, pResult, nLen, NULL, NULL );
return pResult;
}
bool ISysWin::GetSysCpu(int& nCpuRate)
{
HANDLE hEvent;
bool res;
static FILETIME preIdleTime;
static FILETIME preKernelTime;
static FILETIME preUserTime;
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
res = GetSystemTimes(&idleTime,&kernelTime,&userTime);
preIdleTime = idleTime;
preKernelTime = kernelTime;
preUserTime = userTime;
hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//初始值为nonsignaled
WaitForSingleObject(hEvent,500);//等待500毫秒
res = GetSystemTimes(&idleTime,&kernelTime,&userTime);
int idle = CompareFileTime(preIdleTime,idleTime);
int kernel = CompareFileTime(preKernelTime,kernelTime);
int user = CompareFileTime(preUserTime,userTime);
nCpuRate =(int)ceil( 100.0*( kernel + user - idle ) / ( kernel + user ) );
return res;
}
bool ISysWin::GetSysMemory(int& nMemTotal,int& nMemUsed)
{
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if(!GlobalMemoryStatusEx(&memsStat))//如果获取系统内存信息不成功,就直接返回
{
nMemTotal = -1;
nMemUsed = -1;
return false;
}
int nMemFree = memsStat.ullAvailPhys/( 1024.0*1024.0 );
nMemTotal = memsStat.ullTotalPhys/( 1024.0*1024.0 );
nMemUsed= nMemTotal- nMemFree;
return true;
}
bool ISysWin::GetSysDisk(int& nDiskTotal,int& nDiskUsed)
{
static char path[_MAX_PATH];//存储当前系统存在的盘符
int curdrive = _getdrive();
unsigned long lFreeAll = 0UL;
unsigned long lTotalAll = 0UL;
for(int drive = 1; drive <= 26; drive++ )//遍历所有盘符
{
if( !_chdrive( drive ) )
{
sprintf(path, "%c:\\", drive + 'A' - 1 );
ULARGE_INTEGER caller, total, free;
WCHAR wszClassName[_MAX_PATH];
memset(wszClassName,0,sizeof(wszClassName));
MultiByteToWideChar(CP_ACP,0,path,strlen(path)+1,wszClassName,
sizeof(wszClassName)/sizeof(wszClassName[0]));
if (GetDiskFreeSpaceEx(wszClassName, &caller, &total, &free) == 0)
{
qDebug()<<"GetDiskFreeSpaceEx Filed!";
return false;
}
double dTepFree = free.QuadPart/( 1024.0*1024.0 );
double dTepTotal = total.QuadPart/( 1024.0*1024.0 );
//qDebug()<<"Get Windows Disk Information:"<<path<<"--free:"<<dTepFree<<"--total:"<<dTepTotal;
lFreeAll += (unsigned long)ceil(dTepFree);
lTotalAll += (unsigned long)ceil(dTepTotal);
}
}
nDiskUsed = lFreeAll;
nDiskTotal= lTotalAll;
return true;
}
QMap<int,QString> ISysWin::GetAllProcess()
{
HANDLE hProcessSnap; //进程快照的句柄
HANDLE hProcess; //用于获取进程的句柄
PROCESSENTRY32 pe32;//进程信息的结构体
QMap<int,QString> pidMap;//保存所有进程的PID
// 获取系统进程信息的快照
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
qDebug()<<"CreateToolhelp32Snapshot Failed!";// 打印错误信息
if(NULL !=hProcessSnap)
{
CloseHandle( hProcessSnap ); // 关闭进程快照信息
hProcessSnap = NULL;
}
return pidMap;
}
// 在使用之前设置PROCESSENTRY32结构体的初始大小值,如果不初始化dwSize, Process32First 调用会失败.
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )// 开始获取第一个进程的信息,如果获取失败就返回
{
qDebug()<<"Process32First Failed!"; // 打印错误信息
if(NULL !=hProcessSnap)
{
CloseHandle( hProcessSnap ); // 关闭进程快照信息
hProcessSnap = NULL;
}
return pidMap;
}
//开始遍历所有进程
pidMap.clear();
do
{
//加入PID
if(!pidMap.contains((int)pe32.th32ProcessID))
{
QString strProcessName =UnicodeToAnsi(pe32.szExeFile);
pidMap.insert((int)pe32.th32ProcessID,strProcessName);
}
//当然还可以获取到很多其他信息,例如进程名字(szExeFile[MAX_PATH])、父进程PPID(th32ParentProcessID)。。。
/* 附上该结构体信息
typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;
*/
}
while( Process32Next( hProcessSnap, &pe32 ) );// 获取下一个进程的信息
if(NULL !=hProcessSnap)//最后关闭快照句柄
{
CloseHandle( hProcessSnap );
hProcessSnap = NULL;
}
return pidMap;
}
bool ISysWin::GetProcessMemory(int nPid,int& nProcessMemRate)
{
HANDLE hProcess;//该线程的句柄
PROCESS_MEMORY_COUNTERS pmc;//该线程的内存信息结构体
hProcess = OpenProcess( PROCESS_ALL_ACCESS ,FALSE, nPid );//利用最大权限打开该线程并获得句柄
if (NULL == hProcess)
{
qDebug()<<"OpenProcess Failed!";
return false;
}
if ( !GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
qDebug()<<"GetProcessMemoryInfo Failed!";
return false;
}
int nMemTotal = 0;
int nMemUsed = 0;
this->GetSysMemory(nMemTotal,nMemUsed);
double tep = ((int)pmc.WorkingSetSize*1.0);
nProcessMemRate = (int)ceil(100*(tep/(1024.0*1024.0)) / nMemTotal) ;
CloseHandle(hProcess);
return true;
}
最后当然是我的测试类了,
#include <QtCore/QCoreApplication>
#include "ISysInfo.h"
#include "ISysWin.h"
#include <Windows.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ISysInfo* pISys = new ISysWin();//调用WINDOWS实现的子类
while (1)
{
int nCpuRate = -1;
int nMemTotal = -1;
int nMemUsed = -1;
int nDiskTotal = -1;
int nDiskUsed = -1;
int nProcessMemRate = -1;
QMap<int,QString> pidMap;
pISys->GetSysCpu(nCpuRate);
qDebug()<<"CPU Rate:"<<nCpuRate<<"%";
pISys->GetSysMemory(nMemTotal,nMemUsed);
qDebug()<<"Mem Total:"<<nMemTotal<<"\t Mem Used:"<<nMemUsed;
pISys->GetSysDisk(nDiskTotal,nDiskUsed);
qDebug()<<"Disk Total:"<<(nDiskTotal/1024.0)<<"GB \t Disk Used:"<<(nDiskUsed/1024.0)<<"GB";
pISys->GetProcessMemory(6472,nProcessMemRate);
qDebug()<<"PID:6472;\t Mem Rate:"<<nProcessMemRate<<"%";
pidMap = pISys->GetAllProcess();
qDebug()<<"Process Number:"<<pidMap.size();
qDebug()<<"-------------------------------------------------------------------";
Sleep(1000);
}
delete pISys;
return a.exec();
}<span style="color:#ff0000;">
</span>
后期我会继续实现linux下的代码,请继续关注!!!