一、枚举当前的所有进程(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
;
}
}
|