Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11656
Последний выпуск: 19.06.2015

Получение информации о выполняющихся процессах

Автор: Садовой А.Г.
23 января 2006 года

Получить информацию о выполняющихся в данный момент на компьютере процессах можно на основе функций API. Для разных платформ эти функции отличаются, как и подключаемые для этих целей модули. Рассмотрим платформу Win95 и WinNT.

В Win95 (Windows 95/98) код может выглядеть следующим образом:

function GetProcessesWin95(var Proc: TProcArray):Integer;
var
FSnap: THandle;
PE: TProcessEntry32;
PPE: PProcessEntry32;
I: Integer;
begin
If FSnap > 0 then CloseHandle(FSnap);
FSnap:=CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PE.dwSize:=SizeOf(PE);
I:=0;
SetLength(Proc,1000); // заведомо большой массив
If Process32First(FSnap,PE) then
  	repeat
    		New(PPE);
    		PPE^:=PE;
    		Proc[I]:=PPE.szExeFile;
    		I:=I+1;
  	until not Process32Next(FSnap, PE);
Result:=I;
end;

Для работы этого кода нужно подключить в разделе USES модуль TlHelp32 (Help Tool API 32).

Функция возвращает число процессов и записывает их пути в массив-переменную Proc. Тип переменной Proc - обычный массив строк, который нужно описать в разделе описания типов:

type TProcArray = Array of String;

Поясню основные моменты реализации кода. Строка

 
FSnap:=CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);

означает получение "моментального снимка всех процессов". Точнее, в результате ее выполнения мы получаем дескриптор снимка. Функции Process32First и Process32Next позволяют "пробежаться" по всем процессам. О более детальной информации отсылаю читателя к справочной литературе об API.

Для NT-платформы (Windows NT/2000) аналогичный код может выглядеть следующим образом:

function GetProcessesWinNT(var Proc: TProcArray):Integer;
var
Num: Integer;
LP: Array[0..$3FFF-1] of Dword; // заведомо большой массив
CB: DWord;
CBNeeded:DWord;
ProcHndl: THandle;
ModHand: HModule;
ModName: array [0..MAX_PATH] of Char;
I: Integer;
begin
  EnumProcesses(@LP,CB,CBNeeded);
  Num:= CBNeeded div SizeOf(DWORD);
  SetLength(Proc,Num);
 For I:=0 to Num-1 do
  begin
    ProcHndl:=
    OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,LP[I]);
    If GetModuleFileNameEx(ProcHndl,ModHand,ModName,SizeOf(ModName))> 0 then
    Proc[I]:=ModName else Proc[I]:='Unknown';
  end;
IF ProcHndl > 0 then CloseHandle(ProcHndl);
Result:=Num;
end;

Здесь уже используется модуль PSAPI, который необходимо включить в раздел USES. Кому интересно разобраться в деталях данного кода отсылаю к справке по API.

Замечу, что под управлением WINDOWS 2000, в списке процессов я наблюдал иногда "абракадабру" по путям некоторых процессов. Предлагаю в этом вопросе читателю разобраться самостоятельно, а у меня пока до этого не дошли руки. Тем не менее, считаю, что данная статья может послужить хорошим подспорьем, для всех интересующихся данным вопросом.

В конце приведу код для определения платформы компьютера, поскольку он может понадобиться при реализации кода для вывода списка процессов. Оставляю его без комментариев.

function GetPlatform: String;
var VI: TOSVersionInfo;
begin
VI.dwOSVersionInfoSize:=SizeOf(VI);
GetVersionEx(VI);
Case VI.dwPlatformId of
Ver_Platform_Win32s: Result:= 'Win32s';
Ver_Platform_Win32_Windows: Result:='Win95';
Ver_Platform_Win32_NT: Result:='WinNT'
else Result:='Unknown Platform'; 
end;
end;

В моем модуле SysInfo v.3.00 можно найти функции получения информации о выполняемых процессах и о другой системной информации.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
289
19 ноября 2005 года
sadovoya
757 / / 19.11.2005
Мне нравитсяМне не нравится
24 февраля 2015, 20:29:19
Обновления модуля SysInfo для Delphi и Lazarus можно найти на странице http://sadovoya.narod.ru/codes.htm либо в исходниках в этом форуме. Там-же есть на тему системной информации на C++ ("чистом" и с использованием Qt).
2.
289
19 ноября 2005 года
sadovoya
757 / / 19.11.2005
Мне нравитсяМне не нравится
13 марта 2011, 15:49:14
Важное дополнение о функции GetProcessesWinNT().

Чтобы OpenProcess() работал более успешно, надо вызывающей программе повысить привилегии до уровня SeDebugPrivilege (константа SE_DEBUG_NAME). Это дает доступ к процессам вплоть до PROCESS_ALL_ACCESS. Без этого OpenProcess() может не получить \"хэндла\" с запрошенными флагами доступа.

Делается это примерно так. Вставляем до цикла \"For I:=0 to Num-1 do...\" следующий код:

Код:
ImpersonateSelf(SecurityImpersonation);

    OpenThreadToken(

            GetCurrentThread(), //наша программы

            TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,

            FALSE,

            @hToken

            );



    tp.PrivilegeCount:=0;

    tp.Privileges[0].Attributes:=0;

    tp.Privileges[0].Luid:=0;



    cbT:= sizeof(TOKEN_PRIVILEGES);

    LookupPrivilegeValue( 0, SE_DEBUG_NAME, @luidMod );

    tp.PrivilegeCount:= 1;

    tp.Privileges[0].Luid:= luidMod;

    tp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges( hToken, false, @tp, cbT, 0, 0 );

    if (hToken <> 0) then CloseHandle(hToken); //больше не нужен


А в раздел var добавляем переменные:
Код:
cbT : Cardinal;

    hToken : Cardinal;

    tp: TOKEN_PRIVILEGES;

    luidMod: LUID;

Проверил этот метод в Lazarus. В uses подключил модуль Windows. В Delphi должно быть тоже самое. В списке процессов по-прежнему неопределенные процессы присутствуют, но их всего несколько - это системныее процессы самого высшего уровня. Увеличение до PROCESS_ALL_ACCESS флага в OpenProcess() ситуацию не улучшает.

Автор
3.
289
19 ноября 2005 года
sadovoya
757 / / 19.11.2005
Мне нравитсяМне не нравится
5 августа 2010, 05:16:21
"Судя по предыдущему комментарию и в 2000 тоже" - это я перегрелся, судя по своему комментарию :))
4.
289
19 ноября 2005 года
sadovoya
757 / / 19.11.2005
+1 / -0
Мне нравитсяМне не нравится
4 августа 2010, 19:30:59
Да, хендл надо закрывать. Есть проблема с процессами на NT платформах (сам пользуюсь XP и Vista) вероятно в API-функции OpenProcess(). Анализировал ошибки после ее выполнения - чаще всего ошибка доступа. Пробовал разные комбинации ключа, включаю полный доступ - ничего не удалось. Видимо от библиотеки PSAPI придется отказаться. Гораздо лучше ситуация с библиотекой TlHelp32. Там процессы выдаются отлично (в XP и Vista по крайней мере). Судя по предыдущему комментарию и в 2000 тоже. На днях выложу обновленные исходники. Там добавил еще инфу о принтерах и нек. др. Пока тестовая версия, но достаточно работоспособная.
5.
Аноним
Мне нравитсяМне не нравится
8 февраля 2006, 12:12:51
Не знаю как на Windows 2000, а на XP код для Win 95/98 тоже работает. И в первой функции лучше в конце Handle все же закрыть,то есть CloseHandle(FSnap)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог