Dimitry Sibiryakov |
---|
Какие только чудеса проктостоматологической изворотливости демонстрируют программисты только лишь бы не исправлять бага, приводящего к зависанию...
|
Я не разработчик почтовой программы. Моя задача контролировать её работоспособность (если зависла - перезапустить).
Мимопроходящий |
---|
в задачу твою не вникал.
решить можно так: делаешь EnumWindows() для каждого найденного окошка вызываешь GetWindowThreadProcessID() сверяешь полученный PID с нужным тебе ну а дальше, на твоё усмотрение
|
Это действительно вариант. Но надо ли перебирать все существующие окна?
Насколько я понимаю (возможно вы меня поправите), иерархия строится следующим образом: есть процесс, у процесса есть нити, у нитей есть окна, у окон уже свои потомки...
Может всё же есть возможность зная PID запросить только свои нити (скорей всего она будет одна) и там получить список окон?
Leonid Kudryavtsev |
---|
Автор какие-то страсти расказывает... |
Как я понял, слова пользователя Aniskin убедили вас в моей правоте.
При этом я не говорил что у зависшей программы поменялось что-то в Окнах (хотя об этом сказал позже Aniskin), я говорил что у зависшей программы сменилось имя родительского .EXE-файла который я получаю через обращение к её Процессу (поменялось в её процессе, а не в окне). Возможно даже в случае зависания сам GetWindowThreadProcessId выдаёт изначально не её процесс! К сожалению (или счастью), но зависания не так часты, а восстановить надо немедленно, и поиграться перепробовав все идеи не успеваешь.
Leonid Kudryavtsev |
---|
Так же не понятно, что если нужно прибить процесс, зачем автор ищет окна. Нашли процесс, его и прибили.
|
Мне надо убить зависшую программу. Я нахожу окно программы, по нему нахожу процесс и убиваю.
Ну хорошо, я получаю список всех запущенных процессов и могу по нему пробежаться. Дальше что? Как я узнаю что это мой процесс?
Я нахожу свой процесс своей программы в две строки: FindWindow и GetWindowThreadProcessId.
Вы же предлагаете написать 17 строк чтобы перебрать все процессы через Process32Next, потом ещё как-то определить какой из них мой, и говорите что не понимаете меня почему я не делаю вашим образом?
В реальности же, ещё не зная как определить "Зависание", я начал искать по какому критерию могу это обнаружить и заметив через одну из сторонних программ что зависшая программа выдаёт неправильное имя в GetExeNameByProcID, первым делом проверил список процессов:
procedure TForm1.Button1Click(Sender: TObject);
var
hSnapShot: THandle;
ProcInfo: TProcessEntry32;
begin
hSnapShot := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapShot <> THandle(-1)) then
begin
ProcInfo.dwSize := SizeOf(ProcInfo);
if (Process32First(hSnapshot, ProcInfo)) then
begin
Memo1.Lines.Add(ProcInfo.szExeFile);
while (Process32Next(hSnapShot, ProcInfo)) do
Memo1.Lines.Add(ProcInfo.szExeFile);
end;
CloseHandle(hSnapShot);
end;
end;
И octomail.exe в списке не оказалось! То есть, я не могу основываясь на списке процессов найти свою программу (по крайней мере пользуясь единственным известным мне способом - через родительный .exe-файл)
Aniskin |
---|
The Desktop Window Manager assists by seamlessly... |
Правильно ли я понял, что в роли DWM в данном случае выступает explorer? Операционная система (в моём случае это вообще ХР) передала ему права на управление зависшим окном?
Может тогда в WinAPI есть какой-то другой вариант вместо GetWindowThreadProcessID, который указал бы на РЕАЛЬНЫЙ процесс моей программы, а не подставной временно подменяющий моё окно?
Ведь в случае если я пытаясь убить свою программу ошибочно убиваю процесс explorer.exe, и тотчас пытаясь повторить это же действие - то уже реально убиваю свою программу!
На самом деле я совершенно случайно пришёл к этом результату. Я написал код для уничтожения:
procedure TForm1.Button5Click(Sender: TObject);
var H,ProcID:Integer;
begin
H := FindWindow(nil, 'octoMail');
GetWindowThreadProcessId (H, @ProcID);
TerminateProcess( OpenProcess(PROCESS_TERMINATE,False,ProcID), 0);
end;
Нажал один раз - но вместо моей программы перезапустился Рабочий стол (explorer)
Нажал второй раз - опять перезапустился Рабочий стол
Нажал третий - и опять тоже самое...
И уже в отчаянии разочарованно хотел стукнуть последний раз, но палец случайно соскочил с мышки и нажал два раза (но чуть с большей паузой чем DblClick), и о чудо - закрылся Рабочий стол и моя программа... (explorer после этого конечно стартанул заново)
То есть, когда не запущен explorer (которому как я понял DWM передал процесс над зависшей программой), то GetWindowThreadProcessID возвращает реальный PID программы, а если explorer запущен, то GetWindowThreadProcessID возвращает PID Рабочего стола.