Delphi: Получить список запущенных процессов.
26 Декабрь 2008
Я считаю, что данная тема довольно актуальна и для своих программ иногда приходится придумывать механизмы, которые, к примеру, не позволяли запускать одновременно несколько копий программ. Для реализации такого механизма достаточно описать в своем проекте функцию получения списка запущенных процессов и в зависимости от своих нужд работать с полученным списком.
Ниже приведен пример программы которая выводит список процессов. Все комментарии смотрите в исходнике.
Delphi
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,PSAPI, TlHelp32; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function GetProcessList(): TStrings; var eP: TProcessEntry32; hP, snap: THandle; //дескрипторы процесса и снимка hM: hmodule; //дескриптор модуля prcs: array[0..$FFF] of dword; //массив для хранения // дескрипторов процессов cP, cM: cardinal; //количество процессов i: integer; NameProc: array[0..max_path] of char; //имя модуля lP: TStrings; begin lP:=TStringList.Create; lP.Clear; //проверяем версию винды if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then begin //если это Win9x //инициализируем переменные snap := CreateToolhelp32Snapshot(th32cs_snapprocess, 0); if integer(snap) = -1 then begin exit; end else begin eP.dwSize := sizeof(eP); //для Win9x получение списка процессов выполняется по //аналогии с поиском файлов //вызываем функцию для получения первого процесса if Process32First(snap, eP) then //а далее в цикле пока еще есть процессы получаем следующий repeat lP.Add(string(eP.szExeFile));//получаем имя процесса until not Process32Next(snap, eP); end; end else begin //Если WinNT/2000/XP //то в этом случае мы пользуемся Api-функцией перечисления // запущенных процессов //которая заполняет нам наши переменные if not EnumProcesses(@prcs, sizeof(prcs), cP) then begin exit; end; //и далее для каждого дескриптора процесса получаем о нем // информацию for i := 0 to cP div 4 - 1 do begin hP := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, prcs[i]); if hP > 0 then begin EnumProcessModules(hP, @hM, 4, cM); GetModuleFileNameEx(hP, hM, NameProc, sizeof(NameProc)); lP.Add(ExtractFileName(string(NameProc))); //если вы хотите // получить только имена процессов // lP.Add(string(NameProc)); //если вы хотите получить // имена процессов вместе c путем CloseHandle(hP); end; end; end; GetProcessList:=lP; //возвращаем полученный список end; procedure TForm1.Button1Click(Sender: TObject); begin memo1.Lines:=GetProcessList; end; end.


prcs: array[0..$FFF] of dword; //массив для хранения
Вот это не самый правильный фрагмент. Если в системе более, чем 4096 процессов, то только первые 4096 попадут в список. Документация говорит, что если размер использованного буфера cP после функции EnumProcesses равен размеру вашего буфера, то надо снова вызвать EnumProcesses с уже большим буфером. И так до тех пор, пока ваш буфер не будет заполняться до конца. Вот такая вот виндовая технология. ;-)
Понятно, что для домашнего компьютера 4096 весьма значительная и слабо достижимая цифра, но вот для промышленных систем — легко. У нас один банк, работающий на виндах, имеет только одних телнет-соединений более 4000 (уже по одному процессу на соеденение). Так что там количество процессов гораздо больше 4096.
Почему знаю, потому что писал аналогичную функцию и наступил на эти грабли. ;-)
@Александр
Согласен, но не думал что может быть их так много!Оо Спасибо, ценное замечание. =)
По поводу ограничения на повторный запуск копии своей программы это не лучший вариант. С помощью WinAPI ф-ции CreateMutex создается собственно сам мьютекс уникальный для вашей программы. При запуске второго экземпляра вашей проги попытка создать мьютекс с тем же именем будет неудачность. Значит ваша прога уже запущена. И не нужно никакой возни с процессами.
Верно, но ведь это лишь пример, как можно использовать данный алгоритм, возможно не много не удачный… также другими примерами может стать контроль или монитор процессов и т.п. а это уже читателю решать где данный механизм можно применить. Но спасибо большое за столь ценный совет, это приятно :)