您的位置:首页 > 其它

Win32使用Psapi库枚举系统进程信息

2015-05-07 14:35 375 查看


一、枚举当前的所有进程(64位的程序暂时不会处理)

通过EnumProcesses得到当前所有的进程的进程ID,然后调用OpenProcess通过进程ID得到进程句柄,再调用EnumProcessModules来得到该进程的模块句柄,GetModuleBaseName通过进程模块句柄得到进程的名字,GetModuleFileNameEx通过进程模块句柄得到进程的可执行文件名。上面所有函数的参数信息,自行F1到MSDN查询。



[cpp] view
plaincopyprint?





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,来取得该进程的内存使用信息

[cpp] view
plaincopyprint?





//取得进程的内存使用信息

PROCESS_MEMORY_COUNTERS processMemCounters ;

if( ::GetProcessMemoryInfo (porcessHandle, &processMemCounters, sizeof(processMemCounters) ) )

{

processMemCounters.WorkingSetSize; //当前进程的内存使用量单位是byte,该结构体的其他成员的作用请参考MSDN

}


三、获取进程的当前的线程数

通过CreateToolhelp32Snapshot来获取系统中的所有线程快照,第二个参数指定需要包含在内的进程ID,然后通过Thread32First和Thread32Next来遍历该进程快照,通过比对进程ID来确定线程归属于哪个进程。

[cpp] view
plaincopyprint?





//得到当前系统中所有线程的快照

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说明该进程已经退出

}


四、获取进程的当前CPU使用率

通过通过进程ID,调用OpenProcess来获得进程句柄,通过进程句柄,调用GetProcessTimes来得到该进程从开始到现在所使用

[cpp] view
plaincopyprint?





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用来关闭监控进程,并清理相关资源

[cpp] view
plaincopyprint?





//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;

};

[cpp] view
plaincopyprint?





//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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: