Для получения списка процессов необходимо сделать "снимок" состояния системы с помощью функции CreateToolhelp32Snapshot
. Эта функция создает специальный объект, который может хранить информацию о процессах, модулях, нитях и кучах, созданных в системе. Этот объект называется снимком потому, что информация, хранящаяся в нем, актуальна на момент вызова функции CreateToolhelp32Snapshot
; дальнейшие изменения списка процессов, модулей и т. п. не приводят к изменению снимка. Доступ к снимку, как и к большинству объектов системы, осуществляется через его дескриптор. В данном случае функция CreateToolhelp32Snapshot
вызывается с параметром TH32CS_SNAPPROCESS
для получения списка процессов.
Навигация по списку процессов, сохраненных в снимке, осуществляется с помощью функций Process32First
и Process32Next
. Они позволяют получить ряд параметров процесса, главный среди которых —
Не следует путать идентификатор процесса и дескриптор объекта процесса, который используется, например, в функции SetPriorityClass
. Объект процесса — это специальный объект, связанный с процессом, но не тождественный ему. В частности, объект процесса может продолжать существовать уже после того, как сам процесс завершит работу (это позволяет, например, корректно синхронизироваться с уже завершенным процессом при помощи функции WaitForSingleObject
). Через объект процесса можно управлять многими свойствами процесса. Поучить дескриптор объекта процесса по идентификатору процесса можно с помощью функции OpenProcess
.
Код для получения списка процессов показан в листинге 1.42.
procedure TProcessesInfoForm.FillProcessList;
var
SnapProc: THandle;
ProcEntry: TProcessEntry32;
Item: TListItem;
begin
ClearAll;
// Создаем снимок, в котором сохраняем все процессы, а
// затем в цикле получаем информацию о каждом из этих
// процессов, перенося ее в ListProcesses
SnapProc:= CreateToolhelp32Snapshot(TH32CS_SNAPROCESSES, 0);
if SnapProc <> INVALID_HANDLE_VALUE then
try
ProcEntry.dwSize:= SizeOf(TProcessEntry32);
if Process32First(SnapProc, ProcEntry) then repeat
Item:= ListProcesses.Items.Add;
Item.Caption:= ProcEntry.szExeFile;
Item.SubItems.Add(IntToStr(ProcEntry.tb32ProcessID);
Item.SubItems.Add(IntToStr(ProcEntry.th32ParentProcessID));
Item.SubItems.Add(IntToStr(ProcEntry.cntThreads));
// Сохраняем PID в поле Data соответствующего
// элемента списка. Вообще, поле Data имеет тип
// Pointer, а PID — это целое число, но т. к. оба этих
// типа 32-битные, их можно приводить друг к другу
Item.Data:= Pointer(ProcEntry.th32ProcessID);
until not Process32Next(SnapProc, ProcEntry);
finally
CloseHandle(SnapProc);
end
else
begin
ListProcesses.Visible:= False;
LabelProcessError.Caption:=
'Невозможно получить список процессов:'#13#10'Ошибка №' +
IntToStr(GetLastError);
end;
end;