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

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

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

    

[cpp]  view plain copy print ?
  1. DWORD aProcesses[1024], cbNeeded, cProcesses;    
  2. if( !::EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )  
  3. {  
  4.     return;    
  5. }  
  6.   
  7. cProcesses = cbNeeded / sizeof(DWORD); //计算得到的进程个数    
  8. for (unsigned int i = 0; i< cProcesses; ++i)   
  9. {  
  10.     ProcessInfo oneProcess;  
  11.     const DWORD& processID=  aProcesses[i]; //进程ID  
  12.   
  13.     //通过进程ID获得进程句柄  
  14.     HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID);  
  15.     if (nullptr != hProcess )    
  16.     {    
  17.         HMODULE hMod;    
  18.         DWORD cbNeeded;    
  19.   
  20.   //目前该函数只能对32位进程进行处理  
  21.         if(::EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )  
  22.         {    
  23.             //获得进程名  
  24. TCHAR processName[MAX_PATH];  
  25.             ::GetModuleBaseName(hProcess, hMod, oneProcess.processName, sizeof(processName)/sizeof(TCHAR) );  
  26.   
  27.             //获得进程执行文件名  
  28. TCHAR moduleName[MAX_PATH];  
  29.             ::GetModuleFileNameEx(hProcess, hMod, oneProcess.moduleName, sizeof(moduleName)/sizeof(TCHAR));  
  30.         }    
  31.         CloseHandle(hProcess);    
  32.     }    
  33. }  

二、获取进程的内存使用信息

     通过线程ID,调用OpenProcess来获得进程句柄,获得进程句柄之后调用GetProcessMemoryInfo,来取得该进程的内存使用信息

[cpp]  view plain copy print ?
  1. //取得进程的内存使用信息  
  2. PROCESS_MEMORY_COUNTERS processMemCounters ;  
  3. if( ::GetProcessMemoryInfo (porcessHandle, &processMemCounters, sizeof(processMemCounters) ) )  
  4. {  
  5.     processMemCounters.WorkingSetSize; //当前进程的内存使用量单位是byte,该结构体的其他成员的作用请参考MSDN  
  6. }  

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

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

[cpp]  view plain copy print ?
  1.    //得到当前系统中所有线程的快照  
  2.    HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processID);  
  3.    if (INVALID_HANDLE_VALUE == hSnapThread)  
  4.    {  
  5.        return false;  
  6.    }  
  7.   
  8.    THREADENTRY32 te32 = {sizeof(te32)};  
  9.    DWORD nCount = 0;  
  10.    if (Thread32First(hSnapThread, &te32))  
  11.    {  
  12. //遍历当前的所有线程  
  13.        do  
  14.        {  
  15.     //该线程所属的进程ID  
  16.            if( te32.th32OwnerProcessID == processID)  
  17.            {  
  18.     //如果进程ID符合,线程计数加1  
  19.                ++nCount;  
  20.            }  
  21.        } while (Thread32Next(hSnapThread, &te32));  
  22.    }  
  23.    CloseHandle(hSnapThread);  
  24.   
  25.    if(nCount)  
  26.    {  
  27. //nCount就是该进程的线程数  
  28.    }  
  29.    else  
  30.    {  
  31. //如果线程数为0说明该进程已经退出  
  32.    }  

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

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

[cpp]  view plain copy print ?
  1. FILETIME createTime;  
  2. FILETIME exitTime;  
  3. FILETIME kernelTime;  
  4. FILETIME userTime;  
  5. //获取该进程从开始到现在使用的CPU时间  
  6. BOOL bRetCode = ::GetProcessTimes(porcessHandle, &createTime, &exitTime, &kernelTime, &userTime);  
  7.   
  8. if (!bRetCode)  
  9. {  
  10.     return false;  
  11. }  
  12. LARGE_INTEGER lgKernelTime;  
  13. lgKernelTime.HighPart = kernelTime.dwHighDateTime;  
  14. lgKernelTime.LowPart = kernelTime.dwLowDateTime;  
  15.   
  16. LARGE_INTEGER lgUserTime;  
  17. lgUserTime.HighPart = userTime.dwHighDateTime;  
  18. lgUserTime.LowPart = userTime.dwLowDateTime;  
  19.   
  20.   
  21. //从进程启动到现在已经使用的CPU时间, 然后在一段时间后再取一次该值, 用差值除以经过的时间差,就是使用率  
  22. LARGE_INTEGER nowCPUTime;  
  23. nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors;  

五、自己封装的一个类

接口GetAllProcess来获取当前系统中所有的进程的信息,

OpenMonitorProcess来打开需要开始进行监控的进程,参数是需要进程ID

如果进程打开成功,则调用GetProcessStatus获取当前进程的状态信息,如果返回空则说明进程有可能已经退出。两次调用之间相隔最好大于1秒,这样才会使CPU使用率更好计算。

CloseMonitorProcess用来关闭监控进程,并清理相关资源

[cpp]  view plain copy print ?
  1. //ProcessMonitor.h  
  2. #pragma once  
  3. #include <windows.h>  
  4. #include <vector>  
  5.   
  6. //目前只支持32位的程序 64位的程序会失败EnumProcessModules不支持64  
  7. class CProcessMonitor  
  8. {  
  9. public:  
  10.     struct ProcessStatus  
  11.     {  
  12.         ProcessStatus()  
  13.         {  
  14.             memset(this, 0,sizeof(ProcessStatus));  
  15.         }  
  16.   
  17.   
  18.         DWORD processID;  
  19.         HANDLE porcessHandle;  
  20.   
  21.         TCHAR processName[MAX_PATH];  
  22.         TCHAR moduleName[MAX_PATH];  
  23.         SYSTEMTIME processCreateTime;  
  24.   
  25.         SIZE_T nowUseMem;  
  26.         SIZE_T maxUseMem;  
  27.         SYSTEMTIME maxUseMemTime;  
  28.   
  29.         DWORD nowThreadCount;  
  30.         DWORD maxThreadCount;  
  31.         SYSTEMTIME maxThreadCountTime;  
  32.   
  33.         DWORD numberOfProcessors;  
  34.         LARGE_INTEGER lastCheckCPUTime;  
  35.         LARGE_INTEGER lastCPUTime;  
  36.         DWORD nowCPUUse;  
  37.         DWORD maxCPUUse;  
  38.         SYSTEMTIME maxCPUUseTime;  
  39.     };  
  40.   
  41.     struct ProcessInfo  
  42.     {  
  43.         ProcessInfo()  
  44.             :processID(-1)//PID=0 是windows系统的一个固定进程  
  45.         {  
  46.             lstrcpyn(processName, TEXT("Unknown"), _countof(processName));  
  47.             lstrcpyn(moduleName, TEXT("Unknown"), _countof(processName));  
  48.         }  
  49.         DWORD processID;  
  50.         TCHAR processName[MAX_PATH];  
  51.         TCHAR moduleName[MAX_PATH];  
  52.     };  
  53. public:  
  54.     CProcessMonitor(void);  
  55.     ~CProcessMonitor(void);  
  56.   
  57.     static std::vector<ProcessInfo> GetAllProcess();  
  58.   
  59.     bool OpenMonitorProcess(DWORD processID);  
  60.     void CloseMonitorProcess();  
  61.   
  62.     const ProcessStatus* GetProcessStatus();  
  63.   
  64. private:  
  65.     bool GetMemUse();  
  66.     bool GetThreadCount();  
  67.     bool GetCPUUse();  
  68.   
  69. private:  
  70.     ProcessStatus m_processStatus;  
  71. };  

[cpp]  view plain copy print ?
  1. //ProcessMonitro.cpp  
  2. #include "stdafx.h"  
  3. #include "ProcessMonitor.h"  
  4.   
  5. #include <Psapi.h>  
  6. #pragma comment(lib,"psapi.lib")  
  7. #include <TlHelp32.h>  
  8.   
  9.   
  10. CProcessMonitor::CProcessMonitor(void)  
  11. {  
  12.     SYSTEM_INFO sysInfo;  
  13.     GetSystemInfo(&sysInfo);  
  14.     m_processStatus.numberOfProcessors= sysInfo.dwNumberOfProcessors;  
  15.     m_processStatus.numberOfProcessors= 1; //与任务管理器对比 好像是两倍  所以暂时不使用这个  
  16.   
  17.     //进程提权  不明觉厉 好像没效果  
  18.     HANDLE hToken;  
  19.     if ( OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken) )  
  20.     {  
  21.         TOKEN_PRIVILEGES tkp;  
  22.         LookupPrivilegeValue( nullptr,SE_DEBUG_NAME,&tkp.Privileges[0].Luid );//修改进程权限  
  23.         tkp.PrivilegeCount=1;  
  24.         tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;  
  25.         AdjustTokenPrivileges( hToken,FALSE,&tkp,sizeof tkp,nullptr,nullptr );//通知系统修改进程权限  
  26.     }  
  27. }  
  28.   
  29.   
  30. CProcessMonitor::~CProcessMonitor(void)  
  31. {  
  32.     CloseMonitorProcess();  
  33. }  
  34.   
  35. std::vector<CProcessMonitor::ProcessInfo> CProcessMonitor::GetAllProcess()  
  36. {  
  37.   
  38.     std::vector<ProcessInfo> processList;  
  39.     // Get the list of process identifiers.    
  40.     DWORD aProcesses[1024], cbNeeded, cProcesses;    
  41.     if( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )  
  42.     {  
  43.         return processList;    
  44.     }  
  45.   
  46.     cProcesses = cbNeeded / sizeof(DWORD); //计算进程个数    
  47.     for (unsigned int i = 0; i< cProcesses; ++i)   
  48.     {  
  49.         ProcessInfo oneProcess;  
  50.         oneProcess.processID= aProcesses[i];  
  51.   
  52.         HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, oneProcess.processID);  
  53.   
  54.         if (nullptr != hProcess )    
  55.         {    
  56.             HMODULE hMod;    
  57.             DWORD cbNeeded;    
  58.             if( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )  
  59.             {    
  60.                 //取得进程名  
  61.                 ::GetModuleBaseName(hProcess, hMod, oneProcess.processName, sizeof(oneProcess.processName)/sizeof(TCHAR) );  
  62.   
  63.                 //取得全文件名  
  64.                 ::GetModuleFileNameEx(hProcess, hMod, oneProcess.moduleName, sizeof(oneProcess.moduleName)/sizeof(TCHAR));  
  65.   
  66.                 processList.push_back(oneProcess);  
  67.             }    
  68.             CloseHandle( hProcess );    
  69.         }    
  70.     }  
  71.   
  72.     return processList;  
  73. }  
  74.   
  75. bool CProcessMonitor::OpenMonitorProcess(DWORD processID)  
  76. {  
  77.     if(m_processStatus.porcessHandle)  
  78.     {  
  79.         return false;  
  80.     }  
  81.   
  82.     m_processStatus.processID= processID;  
  83.     m_processStatus.porcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE, processID); //获得进程句柄    
  84.   
  85.     if (m_processStatus.porcessHandle)    
  86.     {    
  87.         HMODULE hMod;    
  88.         DWORD cbNeeded;    
  89.         if(EnumProcessModules(m_processStatus.porcessHandle, &hMod, sizeof(hMod), &cbNeeded) ) //枚举进程模块信息    
  90.         {    
  91.             //取得进程名  
  92.             ::GetModuleBaseName(m_processStatus.porcessHandle, hMod, m_processStatus.processName, sizeof(m_processStatus.processName)/sizeof(TCHAR) );  
  93.   
  94.             //取得全文件名  
  95.             TCHAR szModuleName[MAX_PATH] = TEXT("<unknown>");    
  96.             ::GetModuleFileNameEx(m_processStatus.porcessHandle, hMod, m_processStatus.moduleName, sizeof(m_processStatus.moduleName)/sizeof(TCHAR) ) ;  
  97.   
  98.             //获取进程创建时间  //记录当前进程的CPU使用量  
  99.             FILETIME createTime;  
  100.             FILETIME exitTime;  
  101.             FILETIME kernelTime;  
  102.             FILETIME userTime;  
  103.             auto bRetCode = GetProcessTimes(m_processStatus.porcessHandle, &createTime, &exitTime, &kernelTime, &userTime);  
  104.             if (bRetCode)  
  105.             {  
  106.                 FILETIME localFileTime;  
  107.                 FileTimeToLocalFileTime(&createTime, &localFileTime);  
  108.                 FileTimeToSystemTime(&localFileTime, &m_processStatus.processCreateTime);  
  109.   
  110.                 LARGE_INTEGER lgKernelTime;  
  111.                 lgKernelTime.HighPart = kernelTime.dwHighDateTime;  
  112.                 lgKernelTime.LowPart = kernelTime.dwLowDateTime;  
  113.   
  114.                 LARGE_INTEGER lgUserTime;  
  115.                 lgUserTime.HighPart = userTime.dwHighDateTime;  
  116.                 lgUserTime.LowPart = userTime.dwLowDateTime;  
  117.   
  118.                 LARGE_INTEGER nowCPUTime;  
  119.                 nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors;  
  120.   
  121.                 //当前的时间  
  122.                 LARGE_INTEGER nowCheckCPUTime;  
  123.                 FILETIME now;  
  124.                 GetSystemTimeAsFileTime(&now);  
  125.                 nowCheckCPUTime.HighPart= now.dwHighDateTime;  
  126.                 nowCheckCPUTime.LowPart= now.dwLowDateTime;  
  127.   
  128.   
  129.                 m_processStatus.lastCheckCPUTime = nowCheckCPUTime;  
  130.                 m_processStatus.lastCPUTime = nowCPUTime;  
  131.   
  132.                 m_processStatus.maxCPUUseTime= m_processStatus.processCreateTime;  
  133.   
  134.                 Sleep(1000);//GerProcess在短时间内被调用会造成错误  
  135.                 return true;  
  136.             }  
  137.         }  
  138.     }  
  139.   
  140.     CloseMonitorProcess();  
  141.     return false;  
  142. }  
  143.   
  144. void CProcessMonitor::CloseMonitorProcess()  
  145. {  
  146.     if(m_processStatus.porcessHandle)  
  147.     {  
  148.         CloseHandle(m_processStatus.porcessHandle);    
  149.         m_processStatus.porcessHandle= nullptr;  
  150.     }  
  151. }  
  152.   
  153. bool CProcessMonitor::GetMemUse()  
  154. {  
  155.     if(!m_processStatus.porcessHandle)  
  156.     {  
  157.         return false;  
  158.     }  
  159.   
  160.     //取得进程的内存使用信息  
  161.     PROCESS_MEMORY_COUNTERS processMemCounters ;  
  162.     if( !::GetProcessMemoryInfo (m_processStatus.porcessHandle, &processMemCounters, sizeof(processMemCounters) ) )  
  163.     {  
  164.         return false;  
  165.     }  
  166.   
  167.     m_processStatus.nowUseMem= processMemCounters.WorkingSetSize/1024;   //现在的内存使用量 单位是K  
  168.     if(m_processStatus.nowUseMem > m_processStatus.maxUseMem)  
  169.     {  
  170.         m_processStatus.maxUseMem= m_processStatus.nowUseMem;  
  171.         GetLocalTime(&m_processStatus.maxUseMemTime);  
  172.     }  
  173.     processMemCounters.PeakWorkingSetSize;  //内存使用高峰  
  174.     return true;  
  175. }  
  176.   
  177. bool CProcessMonitor::GetThreadCount()  
  178. {  
  179.     if (!(m_processStatus.porcessHandle && m_processStatus.processID))  
  180.     {  
  181.         return false;  
  182.     }  
  183.   
  184.     HANDLE hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, m_processStatus.processID);  
  185.     if (INVALID_HANDLE_VALUE == hSnapThread)  
  186.     {  
  187.         return false;  
  188.     }  
  189.   
  190.     THREADENTRY32 te32 = {sizeof(te32)};  
  191.     DWORD nCount = 0;  
  192.     if (Thread32First(hSnapThread, &te32))  
  193.     {  
  194.         do  
  195.         {  
  196.             if( te32.th32OwnerProcessID == m_processStatus.processID)  
  197.             {  
  198.                 ++nCount;  
  199.             }  
  200.         } while (Thread32Next(hSnapThread, &te32));  
  201.     }  
  202.     CloseHandle(hSnapThread);  
  203.   
  204.     if(!nCount)  
  205.     {  
  206.         return false;  
  207.     }  
  208.   
  209.     m_processStatus.nowThreadCount = nCount;  
  210.     if(m_processStatus.nowThreadCount > m_processStatus.maxThreadCount)  
  211.     {  
  212.         m_processStatus.maxThreadCount= m_processStatus.nowThreadCount;  
  213.         GetLocalTime(&m_processStatus.maxThreadCountTime);  
  214.     }  
  215.     return true;  
  216. }  
  217.   
  218. bool CProcessMonitor::GetCPUUse()  
  219. {  
  220.     if(!(m_processStatus.porcessHandle && m_processStatus.numberOfProcessors))  
  221.     {  
  222.         return false;  
  223.     }  
  224.     FILETIME createTime;  
  225.     FILETIME exitTime;  
  226.     FILETIME kernelTime;  
  227.     FILETIME userTime;  
  228.     auto bRetCode = GetProcessTimes(m_processStatus.porcessHandle, &createTime, &exitTime, &kernelTime, &userTime);  
  229.   
  230.     if (!bRetCode)  
  231.     {  
  232.         return false;  
  233.     }  
  234.     LARGE_INTEGER lgKernelTime;  
  235.     lgKernelTime.HighPart = kernelTime.dwHighDateTime;  
  236.     lgKernelTime.LowPart = kernelTime.dwLowDateTime;  
  237.   
  238.     LARGE_INTEGER lgUserTime;  
  239.     lgUserTime.HighPart = userTime.dwHighDateTime;  
  240.     lgUserTime.LowPart = userTime.dwLowDateTime;  
  241.   
  242.   
  243.     //从进程启动到现在已经使用的CPU时间, 然后在一段时间后再取一次该值, 用差值除以经过的时间差,就是使用率  
  244.     LARGE_INTEGER nowCPUTime;  
  245.     nowCPUTime.QuadPart = (lgKernelTime.QuadPart + lgUserTime.QuadPart)/m_processStatus.numberOfProcessors;  
  246.   
  247.     //当前的时间  
  248.     LARGE_INTEGER nowCheckCPUTime;  
  249.     FILETIME now;  
  250.     GetSystemTimeAsFileTime(&now);  
  251.     nowCheckCPUTime.HighPart= now.dwHighDateTime;  
  252.     nowCheckCPUTime.LowPart= now.dwLowDateTime;  
  253.   
  254.     m_processStatus.nowCPUUse= 100*(nowCPUTime.QuadPart - m_processStatus.lastCPUTime.QuadPart)/(nowCheckCPUTime.QuadPart - m_processStatus.lastCheckCPUTime.QuadPart);  
  255.   
  256.     m_processStatus.lastCheckCPUTime = nowCheckCPUTime;  
  257.     m_processStatus.lastCPUTime = nowCPUTime;  
  258.     if(m_processStatus.nowCPUUse > m_processStatus.maxCPUUse)  
  259.     {  
  260.         m_processStatus.maxCPUUse= m_processStatus.nowCPUUse;  
  261.         GetLocalTime(&m_processStatus.maxCPUUseTime);  
  262.     }  
  263.   
  264. }  
  265.   
  266. const CProcessMonitor::ProcessStatus* CProcessMonitor::GetProcessStatus()  
  267. {  
  268.     if( GetMemUse()  
  269.         && GetCPUUse()  
  270.         && GetThreadCount()  
  271.     )  
  272.     {  
  273.         return &m_processStatus;  
  274.     }  
  275.     else  
  276.     {  
  277.         return nullptr;  
  278.     }  
  279. }  

你可能感兴趣的:(Win32使用Psapi库枚举系统进程信息)