![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Трудности с WMI (инфо о процессах)
Тоха © (2011-01-14 20:36:00)Доброго времени суток.
Используя приведёный исходник, пытаюсь написать оконную программу. Если в консольном приложении всё работает на ура, то в оконном происходит следующее. Когда я останавливаю поток, либо просто жму на кресик закрытия окна (срабатывает обработчик, который освобождает поток), он ни в какую не желает останавливаться, а программа зависает. Как выяснилось, поток упорно ждёт наступления Eventquery.NextEvent. Если после попытки закрыть программу запустить и закрыть любую другую, то поток вполне нормально останавливается.
Объясните, пожалуйста, где я ступил.
исходник консольной проги (свою не привожу, ибо практически то же самое):
program ProcessWatcher;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils, Classes, WbemScripting_TLB, ActiveX;
var
SWbemLocator1: TSWbemLocator;
csSync: _RTL_CRITICAL_SECTION;
type
TCreateProcThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
TStopProcThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
const
WBEM_FLAG_RETURN_IMMEDIATELY = $10;
WBEM_FLAG_FORWARD_ONLY = $20;
{ TCreateProcThread }
procedure TCreateProcThread.Execute;
var
Service: ISWbemServices;
Eventquery: ISWbemEventSource;
objLatestProcess: ISWbemObject;
Prop: OleVariant;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
Service := SWbemLocator1.ConnectServer('.',
'root\cimv2',
'', '',
'',
'', 0, nil);
Eventquery := Service.ExecNotificationQuery(
'select * from __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA ''Win32_Process''',
'WQL',
WBEM_FLAG_RETURN_IMMEDIATELY or WBEM_FLAG_FORWARD_ONLY, nil);
while not Terminated do
begin
objLatestProcess := Eventquery.NextEvent(Integer(INFINITE));
Prop := objLatestProcess;
EnterCriticalSection(csSync);
Writeln('Started: ' + Prop.TargetInstance.Name + #09#09 + DateTimeToStr(Now));
LeaveCriticalSection(csSync);
end;
end;
{ TStopProcThread }
procedure TStopProcThread.Execute;
var
Service: ISWbemServices;
Eventquery: ISWbemEventSource;
objLatestProcess: ISWbemObject;
Prop: OleVariant;
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
Service := SWbemLocator1.ConnectServer('.',
'root\cimv2',
'', '',
'',
'', 0, nil);
Eventquery := Service.ExecNotificationQuery(
'select * from __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA ''Win32_Process''',
'WQL',
WBEM_FLAG_RETURN_IMMEDIATELY or WBEM_FLAG_FORWARD_ONLY, nil);
while not Terminated do
begin
objLatestProcess := Eventquery.NextEvent(Integer(INFINITE));
Prop := objLatestProcess;
EnterCriticalSection(csSync);
Writeln('Stopped: ' + Prop.TargetInstance.Name + #09#09 + DateTimeToStr(Now));
LeaveCriticalSection(csSync);
end;
end;
begin
InitializeCriticalSection(csSync);
Writeln('Process name'#09#09#09'Event date');
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
SWbemLocator1 := TSWbemLocator.Create(nil);
try
TCreateProcThread.Create(false);
TStopProcThread.Create(false);
while True do
Sleep(1);
finally
SWbemLocator1.Free;
end;
end.
DiamondShark (2011-01-16 19:07:00) [1]
> Хорошо, а как заставить его закруглиться?
Вот ты когда написал:
> objLatestProcess := Eventquery.NextEvent(Integer(INFINITE));
ты понимал, что означает каждое слово в этой строчке? Например, INFINITE?
Или просто скописпастил?
Тоха (2011-01-15 02:44:00) [2]Германн, ну посоветуй тогда альтернативу... Я сам уже знаю, что я создал, а как сделать по-другому? Подскажи.
ЗЫ. В сторону хуков смотрел, точнее, WM_SHELL, однако не все программы отлавливает. Разбираться не стал, решил пробовать по-простому, как мне казалось...
Германн (2011-01-15 01:38:00) [3]
> Хорошо, а как заставить его закруглиться? WMI предусматривает
> какие-либо способы, либо вы можете посоветовать другой путь
> решения?
А при чем тут WMI?
Это ты сам создал такую ситуацию.
Тоха (2011-01-15 00:39:00) [4]
> он ждет наступления события , которое ты сам же и приказал
> ему ждать.
Хорошо, а как заставить его закруглиться? WMI предусматривает какие-либо способы, либо вы можете посоветовать другой путь решения?
Сергей М. (2011-01-14 21:50:00) [5]> из обработчика кнопки уже не возвращаемся
А должны ?
В обработчике клика кнопки взводится флаг Terminated, после чего осн.поток на вызове WaitFor до опупения ждет когда доп.лоток соизволит обратить на это внимание, чтобы закруглиться по хозяйству. А доп.поток ни сном ни духом об этом не ведает - он ждет наступления события , которое ты сам же и приказал ему ждать.
DiamondShark (2011-01-14 21:35:00) [6]У тебя модель Apartment, а объекты создаются и используются в разных потоках.
Тоха (2011-01-14 21:09:00) [7]Написал небольшой демо-проект http://zalil.ru/30333955 (Delphi 2010)
Запускаете, потоки стартуют автоматически. Затем нажимаете кнопку Terminate:
CPT.Terminate;
CPT.WaitFor;
SPT.Terminate;
SPT.WaitFor;
Итог - из обработчика кнопки уже не возвращаемся. Чтобы вернуться и прервать-таки потоки необходимо запустить и закрыть произвольную программу.
В чем тут дело и как решить проблему?