使用Psapi接口查看进程状态

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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,来取得该进程的内存使用信息

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//得到当前系统中所有线程的快照
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来得到该进程从开始到现在所使用 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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用来关闭监控进程,并清理相关资源

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//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;
};



?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
//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 ;
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值