-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKillExplorerHighCPUThread.dpr
More file actions
227 lines (202 loc) · 6.04 KB
/
KillExplorerHighCPUThread.dpr
File metadata and controls
227 lines (202 loc) · 6.04 KB
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
program KillExplorerHighCPUThread;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
TLHelp32,
Math;
// 定义缺失的常量
const
THREAD_TERMINATE = $0001;
THREAD_QUERY_INFORMATION = $0040;
// 显式声明OpenThread函数(确保兼容性)
function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall; external 'kernel32.dll' name 'OpenThread';
type
// 自定义线程信息记录
TThreadInfo = record
ThreadID: DWORD;
CPUTime: Int64;
CPUUsage: Double;
end;
TThreadInfoArray = array of TThreadInfo;
// 获取进程ID
function GetProcessID(const ProcessName: string): DWORD;
var
Snapshot: THandle;
ProcessEntry: TProcessEntry32;
begin
Result := 0;
Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if Snapshot <> INVALID_HANDLE_VALUE then
begin
ProcessEntry.dwSize := SizeOf(TProcessEntry32);
if Process32First(Snapshot, ProcessEntry) then
begin
repeat
if AnsiCompareText(ExtractFileName(ProcessEntry.szExeFile), ProcessName) = 0 then
begin
Result := ProcessEntry.th32ProcessID;
Break;
end;
until not Process32Next(Snapshot, ProcessEntry);
end;
CloseHandle(Snapshot);
end;
end;
// 获取指定进程的所有线程
function GetProcessThreads(ProcessID: DWORD): TThreadInfoArray;
var
Snapshot: THandle;
ThreadEntry: TThreadEntry32;
i: Integer;
begin
SetLength(Result, 0);
Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if Snapshot <> INVALID_HANDLE_VALUE then
begin
ThreadEntry.dwSize := SizeOf(TThreadEntry32);
if Thread32First(Snapshot, ThreadEntry) then
begin
repeat
if ThreadEntry.th32OwnerProcessID = ProcessID then
begin
SetLength(Result, Length(Result) + 1);
Result[High(Result)].ThreadID := ThreadEntry.th32ThreadID;
Result[High(Result)].CPUTime := 0;
Result[High(Result)].CPUUsage := 0;
end;
until not Thread32Next(Snapshot, ThreadEntry);
end;
CloseHandle(Snapshot);
end;
end;
// 获取线程的CPU时间
function GetThreadCPUTime(ThreadID: DWORD): Int64;
var
ThreadHandle: THandle;
CreationTime, ExitTime, KernelTime, UserTime: TFileTime;
SystemTime: TSystemTime;
begin
Result := 0;
ThreadHandle := OpenThread(THREAD_QUERY_INFORMATION, False, ThreadID);
if ThreadHandle <> 0 then
begin
if GetThreadTimes(ThreadHandle, CreationTime, ExitTime, KernelTime, UserTime) then
begin
// 把文件时间转换为系统时间
FileTimeToSystemTime(KernelTime, SystemTime);
Result := SystemTime.wMilliseconds + SystemTime.wSecond * 1000 +
SystemTime.wMinute * 60 * 1000 + SystemTime.wHour * 60 * 60 * 1000;
FileTimeToSystemTime(UserTime, SystemTime);
Result := Result + SystemTime.wMilliseconds + SystemTime.wSecond * 1000 +
SystemTime.wMinute * 60 * 1000 + SystemTime.wHour * 60 * 60 * 1000;
end;
CloseHandle(ThreadHandle);
end;
end;
// 计算线程的CPU使用率
procedure CalculateCPUUsage(var Threads: TThreadInfoArray; Interval: Integer);
var
i: Integer;
InitialTimes, FinalTimes: array of Int64;
SystemTime: TSystemTime;
TotalSystemTime: Int64;
begin
SetLength(InitialTimes, Length(Threads));
SetLength(FinalTimes, Length(Threads));
// 获取初始CPU时间
for i := 0 to High(Threads) do
InitialTimes[i] := GetThreadCPUTime(Threads[i].ThreadID);
// 等待一段时间,以便计算CPU使用率
Sleep(Interval);
// 获取最终CPU时间
for i := 0 to High(Threads) do
FinalTimes[i] := GetThreadCPUTime(Threads[i].ThreadID);
// 获取系统总时间
GetLocalTime(SystemTime);
TotalSystemTime := SystemTime.wMilliseconds + SystemTime.wSecond * 1000 +
SystemTime.wMinute * 60 * 1000 + SystemTime.wHour * 60 * 60 * 1000;
// 计算每个线程的CPU使用率
for i := 0 to High(Threads) do
begin
if FinalTimes[i] > InitialTimes[i] then
begin
Threads[i].CPUTime := FinalTimes[i] - InitialTimes[i];
// 计算CPU使用率百分比
Threads[i].CPUUsage := (Threads[i].CPUTime / Interval) * 100;
end;
end;
end;
// 终止指定线程
function TerminateThreadByID(ThreadID: DWORD): Boolean;
var
ThreadHandle: THandle;
begin
Result := False;
ThreadHandle := OpenThread(THREAD_TERMINATE, False, ThreadID);
if ThreadHandle <> 0 then
begin
Result := TerminateThread(ThreadHandle, 0);
CloseHandle(ThreadHandle);
end;
end;
var
ExplorerPID: Integer;
Threads: TThreadInfoArray;
MaxCPUUsage : double;
MaxCPUThreadIndex : Integer;
i : Integer;
begin
try
Writeln('正在查找explorer.exe进程...');
ExplorerPID := GetProcessID('explorer.exe');
if ExplorerPID = 0 then
begin
Writeln('未找到explorer.exe进程!');
Exit;
end;
Writeln('找到explorer.exe进程,PID: ', ExplorerPID);
Writeln('正在分析线程CPU使用率...');
Threads := GetProcessThreads(ExplorerPID);
if Length(Threads) = 0 then
begin
Writeln('未找到explorer.exe的线程!');
Exit;
end;
// 计算CPU使用率,采样间隔为1000毫秒
CalculateCPUUsage(Threads, 1000);
// 找出CPU使用率最高的线程
MaxCPUUsage := 0.0;
MaxCPUThreadIndex := -1;
for i := 0 to High(Threads) do
begin
if Threads[i].CPUUsage > MaxCPUUsage then
begin
MaxCPUUsage := Threads[i].CPUUsage;
MaxCPUThreadIndex := i;
end;
end;
if MaxCPUThreadIndex >= 0 then
begin
Writeln('CPU使用率最高的线程:');
Writeln(' 线程ID: ', Threads[MaxCPUThreadIndex].ThreadID);
Writeln(' CPU使用率: ', Format('%.2f%%', [Threads[MaxCPUThreadIndex].CPUUsage]));
if Threads[MaxCPUThreadIndex].CPUUsage >= 2.0 then
begin
Writeln('CPU使用率超过2%,准备终止线程...');
if TerminateThreadByID(Threads[MaxCPUThreadIndex].ThreadID) then
Writeln('线程终止成功!')
else
Writeln('线程终止失败! 可能缺少权限。');
end
else
Writeln('CPU使用率低于2%,跳过终止操作。');
end
else
Writeln('未找到符合条件的线程!');
except
on E: Exception do
Writeln('错误: ', E.Message);
end;
ReadLn; // 等待用户按键
end.