通过EnumProcesses得到当前所有的进程的进程ID,然后调用OpenProcess通过进程ID得到进程句柄,再调用EnumProcessModules来得到该进程的模块句柄,GetModuleBaseName通过进程模块句柄得到进程的名字,GetModuleFileNameEx通过进程模块句柄得到进程的可执行文件名。上面所有函数的参数信息,自行F1到MSDN查询。
DWORD aProcesses[1024], cbNeeded, cProcesses; if( !::EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) { return; } cProcesses = cbNeeded / sizeof(DWORD); //计算得到的进程个数 for (unsigned int i = 0; i< cProcesses; ++i) { ProcessInfo oneProcess; const DWORD& processID= aProcesses[i]; //进程ID //通过进程ID获得进程句柄 HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID); if (nullptr != hProcess ) { HMODULE hMod; DWORD cbNeeded; //目前该函数只能对32位进程进行处理 if(::EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { //获得进程名 TCHAR processName[MAX_PATH]; ::GetModuleBaseName(hProcess, hMod, oneProcess.processName, sizeof(processName)/sizeof(TCHAR) ); //获得进程执行文件名 TCHAR moduleName[MAX_PATH]; ::GetModuleFileNameEx(hProcess, hMod, oneProcess.moduleName, sizeof(moduleName)/sizeof(TCHAR)); } CloseHandle(hProcess); } }
通过线程ID,调用OpenProcess来获得进程句柄,获得进程句柄之后调用GetProcessMemoryInfo,来取得该进程的内存使用信息
//取得进程的内存使用信息 PROCESS_MEMORY_COUNTERS processMemCounters ; if( ::GetProcessMemoryInfo (porcessHandle, &processMemCounters, sizeof(processMemCounters) ) ) { processMemCounters.WorkingSetSize; //当前进程的内存使用量单位是byte,该结构体的其他成员的作用请参考MSDN }
通过CreateToolhelp32Snapshot来获取系统中的所有线程快照,第二个参数指定需要包含在内的进程ID,然后通过Thread32First和Thread32Next来遍历该进程快照,通过比对进程ID来确定线程归属于哪个进程。
//得到当前系统中所有线程的快照 HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processID); if (INVALID_HANDLE_VALUE == hSnapThread) { return false; } THREADENTRY32 te32 = {sizeof(te32)}; DWORD nCount = 0; if (Thread32First(hSnapThread, &te32)) { //遍历当前的所有线程 do { //该线程所属的进程ID if( te32.th32OwnerProcessID == processID) { //如果进程ID符合,线程计数加1 ++nCount; } } while (Thread32Next(hSnapThread, &te32)); } CloseHandle(hSnapThread); if(nCount) { //nCount就是该进程的线程数 } else { //如果线程数为0说明该进程已经退出 }
通过通过进程ID,调用OpenProcess来获得进程句柄,通过进程句柄,调用GetProcessTimes来得到该进程从开始到现在所使用
FILETIME createTime; FILETIME exitTime; FILETIME kernelTime; FILETIME userTime; //获取该进程从开始到现在使用的CPU时间 BOOL bRetCode = ::GetProcessTimes(porcessHandle, &createTime, &exitTime, &kernelTime, &userTime); if (!bRetCode) { return false; } LARGE_INTEGER lgKernelTime; lgKernelTime.HighPart = kernelTime.dwHighDateTime; lgKernelTime.LowPart = kernelTime.dwLowDateTime; LARGE_INTEGER lgUserTime; lgUserTime.HighPart = userTime.dwHighDateTime; lgUserTime.LowPart = userTime.dwLowDateTime; //从进程启动到现在已经使用的CPU时间, 然后在一段时间后再取一次该值, 用差值除以经过的时间差,就是使用率 LARGE_INTEGER nowCPUTime; nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors;
接口GetAllProcess来获取当前系统中所有的进程的信息,
OpenMonitorProcess来打开需要开始进行监控的进程,参数是需要进程ID
如果进程打开成功,则调用GetProcessStatus获取当前进程的状态信息,如果返回空则说明进程有可能已经退出。两次调用之间相隔最好大于1秒,这样才会使CPU使用率更好计算。
CloseMonitorProcess用来关闭监控进程,并清理相关资源
//ProcessMonitor.h #pragma once #include <windows.h> #include <vector> //目前只支持32位的程序 64位的程序会失败EnumProcessModules不支持64 class CProcessMonitor { public: struct ProcessStatus { ProcessStatus() { memset(this, 0,sizeof(ProcessStatus)); } DWORD processID; HANDLE porcessHandle; TCHAR processName[MAX_PATH]; TCHAR moduleName[MAX_PATH]; SYSTEMTIME processCreateTime; SIZE_T nowUseMem; SIZE_T maxUseMem; SYSTEMTIME maxUseMemTime; DWORD nowThreadCount; DWORD maxThreadCount; SYSTEMTIME maxThreadCountTime; DWORD numberOfProcessors; LARGE_INTEGER lastCheckCPUTime; LARGE_INTEGER lastCPUTime; DWORD nowCPUUse; DWORD maxCPUUse; SYSTEMTIME maxCPUUseTime; }; struct ProcessInfo { ProcessInfo() :processID(-1)//PID=0 是windows系统的一个固定进程 { lstrcpyn(processName, TEXT("Unknown"), _countof(processName)); lstrcpyn(moduleName, TEXT("Unknown"), _countof(processName)); } DWORD processID; TCHAR processName[MAX_PATH]; TCHAR moduleName[MAX_PATH]; }; public: CProcessMonitor(void); ~CProcessMonitor(void); static std::vector<ProcessInfo> GetAllProcess(); bool OpenMonitorProcess(DWORD processID); void CloseMonitorProcess(); const ProcessStatus* GetProcessStatus(); private: bool GetMemUse(); bool GetThreadCount(); bool GetCPUUse(); private: ProcessStatus m_processStatus; };
//ProcessMonitro.cpp #include "stdafx.h" #include "ProcessMonitor.h" #include <Psapi.h> #pragma comment(lib,"psapi.lib") #include <TlHelp32.h> CProcessMonitor::CProcessMonitor(void) { SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); m_processStatus.numberOfProcessors= sysInfo.dwNumberOfProcessors; m_processStatus.numberOfProcessors= 1; //与任务管理器对比 好像是两倍 所以暂时不使用这个 //进程提权 不明觉厉 好像没效果 HANDLE hToken; if ( OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken) ) { TOKEN_PRIVILEGES tkp; LookupPrivilegeValue( nullptr,SE_DEBUG_NAME,&tkp.Privileges[0].Luid );//修改进程权限 tkp.PrivilegeCount=1; tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges( hToken,FALSE,&tkp,sizeof tkp,nullptr,nullptr );//通知系统修改进程权限 } } CProcessMonitor::~CProcessMonitor(void) { CloseMonitorProcess(); } std::vector<CProcessMonitor::ProcessInfo> CProcessMonitor::GetAllProcess() { std::vector<ProcessInfo> processList; // Get the list of process identifiers. DWORD aProcesses[1024], cbNeeded, cProcesses; if( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) { return processList; } cProcesses = cbNeeded / sizeof(DWORD); //计算进程个数 for (unsigned int i = 0; i< cProcesses; ++i) { ProcessInfo oneProcess; oneProcess.processID= aProcesses[i]; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, oneProcess.processID); if (nullptr != hProcess ) { HMODULE hMod; DWORD cbNeeded; if( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) ) { //取得进程名 ::GetModuleBaseName(hProcess, hMod, oneProcess.processName, sizeof(oneProcess.processName)/sizeof(TCHAR) ); //取得全文件名 ::GetModuleFileNameEx(hProcess, hMod, oneProcess.moduleName, sizeof(oneProcess.moduleName)/sizeof(TCHAR)); processList.push_back(oneProcess); } CloseHandle( hProcess ); } } return processList; } bool CProcessMonitor::OpenMonitorProcess(DWORD processID) { if(m_processStatus.porcessHandle) { return false; } m_processStatus.processID= processID; m_processStatus.porcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID); //获得进程句柄 if (m_processStatus.porcessHandle) { HMODULE hMod; DWORD cbNeeded; if(EnumProcessModules(m_processStatus.porcessHandle, &hMod, sizeof(hMod), &cbNeeded) ) //枚举进程模块信息 { //取得进程名 ::GetModuleBaseName(m_processStatus.porcessHandle, hMod, m_processStatus.processName, sizeof(m_processStatus.processName)/sizeof(TCHAR) ); //取得全文件名 TCHAR szModuleName[MAX_PATH] = TEXT("<unknown>"); ::GetModuleFileNameEx(m_processStatus.porcessHandle, hMod, m_processStatus.moduleName, sizeof(m_processStatus.moduleName)/sizeof(TCHAR) ) ; //获取进程创建时间 //记录当前进程的CPU使用量 FILETIME createTime; FILETIME exitTime; FILETIME kernelTime; FILETIME userTime; auto bRetCode = GetProcessTimes(m_processStatus.porcessHandle, &createTime, &exitTime, &kernelTime, &userTime); if (bRetCode) { FILETIME localFileTime; FileTimeToLocalFileTime(&createTime, &localFileTime); FileTimeToSystemTime(&localFileTime, &m_processStatus.processCreateTime); LARGE_INTEGER lgKernelTime; lgKernelTime.HighPart = kernelTime.dwHighDateTime; lgKernelTime.LowPart = kernelTime.dwLowDateTime; LARGE_INTEGER lgUserTime; lgUserTime.HighPart = userTime.dwHighDateTime; lgUserTime.LowPart = userTime.dwLowDateTime; LARGE_INTEGER nowCPUTime; nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors; //当前的时间 LARGE_INTEGER nowCheckCPUTime; FILETIME now; GetSystemTimeAsFileTime(&now); nowCheckCPUTime.HighPart= now.dwHighDateTime; nowCheckCPUTime.LowPart= now.dwLowDateTime; m_processStatus.lastCheckCPUTime = nowCheckCPUTime; m_processStatus.lastCPUTime = nowCPUTime; m_processStatus.maxCPUUseTime= m_processStatus.processCreateTime; Sleep(1000);//GerProcess在短时间内被调用会造成错误 return true; } } } CloseMonitorProcess(); return false; } void CProcessMonitor::CloseMonitorProcess() { if(m_processStatus.porcessHandle) { CloseHandle(m_processStatus.porcessHandle); m_processStatus.porcessHandle= nullptr; } } bool CProcessMonitor::GetMemUse() { if(!m_processStatus.porcessHandle) { return false; } //取得进程的内存使用信息 PROCESS_MEMORY_COUNTERS processMemCounters ; if( !::GetProcessMemoryInfo (m_processStatus.porcessHandle, &processMemCounters, sizeof(processMemCounters) ) ) { return false; } m_processStatus.nowUseMem= processMemCounters.WorkingSetSize/1024; //现在的内存使用量 单位是K if(m_processStatus.nowUseMem > m_processStatus.maxUseMem) { m_processStatus.maxUseMem= m_processStatus.nowUseMem; GetLocalTime(&m_processStatus.maxUseMemTime); } processMemCounters.PeakWorkingSetSize; //内存使用高峰 return true; } bool CProcessMonitor::GetThreadCount() { if (!(m_processStatus.porcessHandle && m_processStatus.processID)) { return false; } HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, m_processStatus.processID); if (INVALID_HANDLE_VALUE == hSnapThread) { return false; } THREADENTRY32 te32 = {sizeof(te32)}; DWORD nCount = 0; if (Thread32First(hSnapThread, &te32)) { do { if( te32.th32OwnerProcessID == m_processStatus.processID) { ++nCount; } } while (Thread32Next(hSnapThread, &te32)); } CloseHandle(hSnapThread); if(!nCount) { return false; } m_processStatus.nowThreadCount = nCount; if(m_processStatus.nowThreadCount > m_processStatus.maxThreadCount) { m_processStatus.maxThreadCount= m_processStatus.nowThreadCount; GetLocalTime(&m_processStatus.maxThreadCountTime); } return true; } bool CProcessMonitor::GetCPUUse() { if(!(m_processStatus.porcessHandle && m_processStatus.numberOfProcessors)) { return false; } FILETIME createTime; FILETIME exitTime; FILETIME kernelTime; FILETIME userTime; auto bRetCode = GetProcessTimes(m_processStatus.porcessHandle, &createTime, &exitTime, &kernelTime, &userTime); if (!bRetCode) { return false; } LARGE_INTEGER lgKernelTime; lgKernelTime.HighPart = kernelTime.dwHighDateTime; lgKernelTime.LowPart = kernelTime.dwLowDateTime; LARGE_INTEGER lgUserTime; lgUserTime.HighPart = userTime.dwHighDateTime; lgUserTime.LowPart = userTime.dwLowDateTime; //从进程启动到现在已经使用的CPU时间, 然后在一段时间后再取一次该值, 用差值除以经过的时间差,就是使用率 LARGE_INTEGER nowCPUTime; nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors; //当前的时间 LARGE_INTEGER nowCheckCPUTime; FILETIME now; GetSystemTimeAsFileTime(&now); nowCheckCPUTime.HighPart= now.dwHighDateTime; nowCheckCPUTime.LowPart= now.dwLowDateTime; m_processStatus.nowCPUUse= 100*(nowCPUTime.QuadPart - m_processStatus.lastCPUTime.QuadPart)/(nowCheckCPUTime.QuadPart - m_processStatus.lastCheckCPUTime.QuadPart); m_processStatus.lastCheckCPUTime = nowCheckCPUTime; m_processStatus.lastCPUTime = nowCPUTime; if(m_processStatus.nowCPUUse > m_processStatus.maxCPUUse) { m_processStatus.maxCPUUse= m_processStatus.nowCPUUse; GetLocalTime(&m_processStatus.maxCPUUseTime); } } const CProcessMonitor::ProcessStatus* CProcessMonitor::GetProcessStatus() { if( GetMemUse() && GetCPUUse() && GetThreadCount() ) { return &m_processStatus; } else { return nullptr; } }
http://baike.baidu.com/link?url=uJdxjnGSdPHl_MOr-p1wnKbovuOmRAlCqsd4JlaKRBOp6mHNBHl8RqV92-k0kkRAt7QHWvsx2mjpj2S1S9XUMa