Как сделать, так что бы в ListBox можно было бы отразить процессы, происходящие в данный момент в системе и при выборе из списка специальной кнопкой их закрывать? Примерно догадываюсь, как это сделать, но как формализовать не додумаюсь? Знаю, что надо сделать снимок системы через SnapShot, подключить модуль Thelp32, а как дальше?
Сообщение отредактировано: Atreides -
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
DRKB3 -> Системные функции и WinAPI -> Windows -> Процессы, потоки, память, задачи -> Список задач, процессы и приоритеты -> Как получить список процессов?
и
DRKB3 -> Системные функции и WinAPI -> Windows -> Запуск и завершение приложений -> Как завершить любой процесс, в том числе и системный
У меня только версия 2.3 и там есть пример просмотра и завершения процессов, но, к сожалению, только для винды 98, а, начиная с NT уже не работает. Пока нет времени, что бы скачать новую версию. Мне осталась только третья часть задания: 1. Создать список процессов. Кроме имен процессов, сохраняемых в массиве Pr_Names, необходимо сохранять в дополнительном массиве идентификаторы процессов. 2. Получить номер (индекс) выделенного мышью имени завершаемого процесса, используя метод ListBox1.ItemIndex и соответствующий ему идентификатор процесса. 3. По идентификатору процесса получить его описатель, используя функцию OpenProcess(). 4. Если описатель получен, завершить процесс, используя полученный описатель. Я написал получение списка процессов, идентификаторов процессов и базовых приоритетов потоков осталось только сделать кнопку (Button2) завершения выбранного процесса из списка, а вот как это сделать? К тому же нужно сделать, так что бы кнопка делалась активной только когда выбирается процесс из списка ListBox, это как можно сделать? Для завершения процесса используется функция TerminateProcess ( HandleProc, ExitCode). Значение описателя необходимо получить по идентификатору процесса с помощью функции OpenProcess ( PROCESS_TERMINATE)?
procedure TForm1.Button1Click(Sender: TObject); var SH : Thandle; Num, I : Integer; PPE : TProcessEntry32; Pr_names : array [0..50] of string; begin Num := 0; // получение снимка состояния системы SH := CreateToolHelp32SnapShot(Th32cs_SnapAll, 0); // выделение из снимка имени первого процессов PPE.dwSize := sizeof (ProcessEntry32); Process32First(SH, PPE); Pr_Names [Num] := PPE.szExeFile; // получение имен других процессов while Process32Next(SH, PPE) do begin Num := Num + 1; Pr_Names [Num] := PPE.szExeFile; end; Listbox1.Clear; // вывод списка имен выполняющихся процессов for I := 0 to Num do Listbox1.Items.Add (Pr_Names [I] ); // освобождение ресурса - снимка состояния системы CloseHandle(SH) end;
procedure TForm1.BitBtn1Click(Sender: TObject); begin Close; end;
procedure TForm1.N3Click(Sender: TObject); begin Close; end;
procedure TForm1.Button3Click(Sender: TObject); var Sh : Thandle; Th : TTHREADENTRY32; LstIt : TlistItem; begin Sh := CreateToolHelp32Snapshot (TH32CS_SNAPALL,0); Th.dwSize := sizeof (TTHREADEntry32); Thread32First(sh,Th); ListView1.Items.Clear; LstIt :=ListView1.Items.Add; LstIt.Caption:=IntToStr(Th.th32OwnerProcessID); LstIt.SubItems.Add(IntToStr(Th.tpBasePri)); repeat LstIt :=ListView1.Items.Add; LstIt.Caption:=IntToStr(Th.th32OwnerProcessID); LstIt.SubItems.Add(IntToStr(Th.tpBasePri)) until not Thread32Next (sh,Th); CloseHandle(Sh); end;
end.
Сообщение отредактировано: Atreides -
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
// Функция завершения процесса - проверено под XP function ProcessTerminate(dwPID:Cardinal):Boolean; var hToken:THandle; SeDebugNameValue:Int64; tkp:TOKEN_PRIVILEGES; ReturnLength:Cardinal; hProcess:THandle; begin Result:=false; if not OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then exit;
if not LookupPrivilegeValue(nil, 'SeDebugPrivilege', SeDebugNameValue) then begin CloseHandle(hToken); exit; end;
AdjustTokenPrivileges(hToken,false,tkp,SizeOf(tkp),tkp,ReturnLength); if GetLastError()<> ERROR_SUCCESS then exit;
hProcess := OpenProcess(PROCESS_TERMINATE, FALSE, dwPID); if hProcess = 0 then exit;
if not TerminateProcess(hProcess, DWORD(-1)) then exit; CloseHandle( hProcess );
tkp.Privileges[0].Attributes := 0; AdjustTokenPrivileges(hToken, FALSE, tkp, SizeOf(tkp), tkp, ReturnLength); if GetLastError() <> ERROR_SUCCESS then exit;
Result:=true; end;
// Немного поправляем генерацию массива строк: procedure TForm1.Button1Click(Sender: TObject); var SH: Thandle; Num, I: Integer; PPE: TProcessEntry32; Pr_names : array [0..50] of string; begin Num := 0; SH := CreateToolHelp32SnapShot(Th32cs_SnapAll, 0); PPE.dwSize := sizeof (ProcessEntry32); Process32First(SH, PPE); Pr_Names [Num] := PPE.szExeFile;
while Process32Next(SH, PPE) do begin Num := Num + 1; // Храним в самой строке и ProcessID Pr_Names [Num] := '(' + inttostr(ppe.th32ProcessID) + ') ' + PPE.szExeFile; end;
Listbox1.Clear; for I := 0 to Num do Listbox1.Items.Add(Pr_Names[I]); CloseHandle(SH) end;
// Изначально button2.enabled = false // активируется кнопка завершения процесса только при выборе // некоторого элемента в ListBox-е procedure TForm1.ListBox1Click(Sender: TObject); begin Button2.Enabled := (ListBox1.ItemIndex <> -1); end;
// Выделяем из строки ProcessID, сообщаем и удаляем процесс... procedure TForm1.Button2Click(Sender: TObject); var s: string; begin s := ListBox1.Items[ListBox1.ItemIndex]; s := copy(s, pos('(', s) + 1, pos(')', s) - pos('(', s) - 1); showmessage('process #' + s + ' will be destroyed');
Зачем править эту строку: Pr_Names [Num] := '(' + inttostr(ppe.th32ProcessID) + ') ' + PPE.szExeFile; А комментарии к function ProcessTerminate можно расписать?
P.S. Извиняюсь, скрипт [code] в этом инет-клубе не работает.
Сообщение отредактировано: Atreides -
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
ProcessTreminate взята из DRKB 2.3 - там есть комментарии (я удалил потому, что у меня Delphi не поддерживает кириллицу...)
Цитата
Зачем править эту строку:
Затем, чтобы тебе не пришлось после того, как ты вызвал "Удалить процесс" еще раз проходить по всему списку процессов с помощью CreateToolHelp32SnapShot (двойная работа!!!) и искать ProcessID по известному имени... После исправления, которое я сделал, ProcessID хранится рядом с именем процесса в ListBox-е, и его надо только вытащить оттуда, что и делается в Button2.OnClick.
А как сделать, что бы после нажатия кнопки завершения процесса содержание ListBox1 обновлялось? Я пробовал дописать ListBox1.Refresh, но список не обновляется.
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
Как реализовать, чтобы для выбранного процесса из списка ListBox’a вывести сведения о его приоритете, количестве потоков и об используемых им кучах, используя компонент StringGrid? Процесс выбирать с помощью мыши в списке из окна Listbox’а.
Цитата
Добавь вызов Button1Click, чтобы заново сгенерировать список процессов.
В смысле код из под Button1Click добавить к кнопке завершения процесса или как?
Сообщение отредактировано: Atreides -
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
Вот нашел тут одну ссылку, но она на C, а как перегнать на Delphi?
Цитата
Мониторинг выполняющихся в системе процессов – основа всех приложений для наблюдения за работой информационных систем и их пользователей. Для отслеживания появления в системе новых приложений или завершения выполнявшихся можно использовать два способа: 1. периодическое выполнение снимка состояния системы и его анализ, для чего приложение, рассмотренное в п.1.1.1, подключается к обработчику прерываний таймера. Это просто, но неэффективно – приложения не запускаются и не завершаются то и дело. 2. подключение к процедуре запуска и завершения процессов с помощью функции ядра PsSetCreateProcessNotifyRoutine(), описанной в Windows 2000 DDK, путем регистрации функции обратного вызова. Это не так просто, как хотелось бы, но более эффективно.
1.4 Функция NtQuerySystemInformation
Различная системная информация доступна через функцию NtQuerySystemInformation. Описание приведено в стиле С для интересующихся.
NTSTATUS NtQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );
SystemInformationClass указывает тип информации, которую необходимо получить, SystemInformation - это указатель на результирующий буфер, SystemInformationLength - размер этого буфера, ReturnLength – количество записанных байт. Для перечисления запущенных процессов следует установить в параметр SystemInformationClass значение SystemProcessesAndThreadsInformation. #define SystemInformationClass 5 Возвращаемая структура в буфере SystemInformation:
А что, собственно, там перегонять? Описания структур? В DRKB приведено несколько примеров работы с NtQuerySystemInformation, посмотри как это делается ...
С помощью NtQuerySystemInformation, можно получить вот эти сведения о приоритете и количестве потоков, об используемых кучах процессом? Я пример скачать не могу, может ссылка битая?
Сообщение отредактировано: Atreides -
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
У меня подобное задание: нужно разработать приложение для вывода всех процессов в отдельном ListBox, получения их модулей и вывода в StringGrid, при выборе процесса из ListBox1, сведений о времени старта процесса, времени работы в режиме ядра и режиме пользователя. С выводом процессов и модулей я справилась, осталось вывести сведения о времени старта процесса, времени работы в режиме ядра и режиме пользователя в StringGrid.
var Form1 : TForm1; Nomp : Integer; Pr_num : array [0..50] of integer; SHV : Thandle;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var SH : Thandle; Num,I : Integer; PPE : TProcessEntry32; Pr_names : array [0..50] of string;
begin Num := 0; // получение снимка состояния системы SH := CreateToolHelp32SnapShot(Th32cs_SnapAll, 0); // выделение из снимка имени первого процессов PPE.dwSize := sizeof (ProcessEntry32); Process32First(SH, PPE); Pr_Names [Num] := PPE.szExeFile; Pr_num [Num] := PPE.th32ProcessID; // получение имен других процессов while Process32Next(SH, PPE) do begin Num := Num + 1; Pr_Names [Num] := PPE.szExeFile; Pr_num [Num] := PPE.th32ProcessID; end; Listbox1.Clear; // вывод списка имен выполняющихся процессов for I := 0 to Num do begin Listbox1.Items.Add (Pr_Names [I] ); end; // освобождение ресурса - снимка состояния системы CloseHandle(SH) end;
procedure TForm1.ListBox1Click(Sender: TObject); type TszModule = array [0..255] of char; var Num, k : integer; Modul : TMODULEENTRY32; Mod_name : string; // - имя модуля
begin
ListBox2.Clear; Nomp := Pr_num [ListBox1.ItemIndex]; Label1.Caption := IntTostr(Nomp); SHV := CreateToolHelp32Snapshot ( TH32CS_SnapMODULE, Nomp); Modul.dwSize := sizeof (TMODULEEntry32); Module32First(SHV, Modul); Mod_Name :=''; for k:=0 to 255 do begin if Modul.szModule[k]<>#0 then Mod_Name := Mod_Name + Modul.szModule[k] else break; end; ListBox2.Items.Add(Mod_Name);
// получение имен других модулей
while Module32Next(SHV, Modul) do begin Mod_Name :=''; for k:=0 to 255 do begin if Modul.szModule[k]<>#0 then Mod_Name := Mod_Name + Modul.szModule[k] else break; end; ListBox2.Items.Add(Mod_Name); end;
end;
procedure TForm1.FormCreate(Sender: TObject); begin StringGrid1.Cells[0,0]:='Время старта'; StringGrid1.Cells[1,0]:='UT'; StringGrid1.Cells[2,0]:='KT'; StringGrid1.Cells[0,1]:=GetProcessTimes(UserTime,TFileTime);
Написал передачу параметров процессов в StringGrid? А как определить время работы процесса в режиме пользователя (UserTime) и ядра (KernelTime), а так же его время старта?
var Form1: TForm1; SH : Thandle; ListBox1: TListBox; Num, I ,a : Integer; PPE : TProcessEntry32; Pr_names : array [0..50] of string; Pr_num : array [0..50] of TProcessEntry32;
procedure TForm1.Button1Click(Sender: TObject); begin Num := 0; // получение снимка состояния системы SH := CreateToolHelp32SnapShot(Th32cs_SnapAll, 0); // выделение из снимка имени первого процессов PPE.dwSize := sizeof (ProcessEntry32); Process32First(SH, PPE); Pr_Names [Num] := PPE.szExeFile; Pr_num [Num]:=PPE; // получение имен других процессов while Process32Next(SH, PPE) do begin Num := Num + 1; Pr_Names [Num] := PPE.szExeFile; Pr_num [Num]:=PPE; end; Listbox1.Clear; // вывод списка имен выполняющихся процессов for I := 0 to Num do Listbox1.Items.Add(Pr_Names[I]); // освобождение ресурса - снимка состояния системы CloseHandle(SH); end; procedure TForm1.Button2Click(Sender: TObject); begin Sh := CreateToolHelp32Snapshot (TH32CS_SNAPALL,0); Th.dwSize := sizeof (TTHREADEntry32); Thread32First(sh,Th); ListView1.Items.Clear; LstIt :=ListView1.Items.Add; LstIt.Caption:=IntToStr(Th.th32OwnerProcessID); LstIt.SubItems.Add(IntToStr(Th.tpBasePri)); repeat LstIt :=ListView1.Items.Add; LstIt.Caption:=IntToStr(Th.th32OwnerProcessID); LstIt.SubItems.Add(IntToStr(Th.tpBasePri)) until not Thread32Next (sh,Th); CloseHandle(Sh);
end;
procedure TForm1.ListBox1Click(Sender: TObject); begin StringGrid1.Cells[0,1]:=IntToStr(Pr_num[ListBox1.ItemIndex].th32ProcessID); StringGrid1.Cells[1,1]:=IntToStr(Pr_num[ListBox1.ItemIndex].th32ModuleID); StringGrid1.Cells[2,1]:=IntToStr(Pr_num[ListBox1.ItemIndex].cntThreads); end;
Доделал я это задание (получить список выполняющихся процессов в системе, вывести модули выбранного процесса и его потоки, идентификатор, время старта, работы в режиме ядра и пользователя), если кому интересно, то вот код:
var Form1 : TForm1; Nomp : Integer; Pr_num : array [0..50] of integer; SHV : Thandle; //Pr_nam : array [0..50] of TProcessEntry32; H:THandle;
N:integer; Pr_nam : array [0..50] of TProcessEntry32;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); var SH : Thandle; Num,I : Integer; PPE : TProcessEntry32; Pr_names : array [0..50] of string; //integer
begin Num := 0; // получение снимка состояния системы SH := CreateToolHelp32SnapShot(Th32cs_SnapAll, 0); // выделение из снимка имени первого процессов PPE.dwSize := sizeof (ProcessEntry32); Process32First(SH, PPE); Pr_Names [Num] := PPE.szExeFile; //cntThreads; Pr_num [Num] := PPE.th32ProcessID; Pr_nam[Num]:=PPE; // получение имен других процессов while Process32Next(SH, PPE) do begin Num := Num + 1; Pr_Names [Num] := PPE.szExeFile; //cntThreads; Pr_num [Num] := PPE.th32ProcessID; Pr_nam[Num]:=PPE; end; Listbox1.Clear; // вывод списка имен выполняющихся процессов for I := 0 to Num do begin Listbox1.Items.Add (Pr_Names [I]); //(inttostr(Pr_Names [I] )); end; // освобождение ресурса - снимка состояния системы CloseHandle(SH) end;
procedure TForm1.ListBox1Click(Sender: TObject); type TszModule = array [0..255] of char; var Num, k : integer; Modul : TMODULEENTRY32; Mod_name : string; // - имя модуля //Pr_nam : array [0..50] of TProcessEntry32; start,ex,KT,UT,LFT:TFileTime; ST:TSystemTime; q:THandle;
begin
ListBox2.Clear; Nomp := Pr_num [ListBox1.ItemIndex]; //Label1.Caption := IntTostr(Nomp); SHV := CreateToolHelp32Snapshot ( TH32CS_SnapMODULE, Nomp); Modul.dwSize := sizeof (TMODULEEntry32); Module32First(SHV, Modul); Mod_Name :=''; for k:=0 to 255 do begin if Modul.szModule[k]<>#0 then Mod_Name := Mod_Name + Modul.szModule[k] else break; end; ListBox2.Items.Add(Mod_Name);
// получение имен других модулей
while Module32Next(SHV, Modul) do begin Mod_Name :=''; for k:=0 to 255 do begin if Modul.szModule[k]<>#0 then Mod_Name := Mod_Name + Modul.szModule[k] else break; end; ListBox2.Items.Add(Mod_Name); end; begin N:=Pr_num [ListBox1.ItemIndex]; q:=OpenProcess(PROCESS_QUERY_INFORMATION,true,N);
begin GetProcessTimes(q,start,ex,KT,UT); FileTimeToLocalFileTime(start,LFT); FileTimeToSystemTime(LFT,ST);
StringGrid1.cells[0,1]:=IntToStr(Nomp);//(Pr_nam[ListBox1.ItemIndex].th32ProcessID); StringGrid1.cells[1,1]:=IntToStr(Pr_nam[ListBox1.ItemIndex].cntThreads); Form1.StringGrid1.Cells[2,1]:=IntToStr(ST.wHour)+':'+ IntToStr(ST.wMinute)+':'+IntToStr(ST.wSecond); end; begin FileTimeToLocalFileTime(UT,LFT); FileTimeToSystemTime(LFT,ST); Form1.StringGrid1.Cells[3,1]:=IntToStr(ST.wSecond)+':'+IntToStr(ST.wMilliseconds);
end; begin FileTimeToLocalFileTime(KT,LFT); FileTimeToSystemTime(LFT,ST); Form1.StringGrid1.Cells[4,1]:=IntToStr(ST.wSecond)+':'+IntToStr(ST.wMilliseconds);
end; end;
end;
procedure TForm1.FormCreate(Sender: TObject); begin
Может, кто знает, как получить имя файла и его версию по имени созданного им процесса? То есть: есть список процессов (см. выше) и по клику на имени процесса выводить имя файла создавшего его и его версию?
--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!