Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Трудности с 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;


Итог - из обработчика кнопки уже не возвращаемся. Чтобы вернуться и прервать-таки потоки необходимо запустить и закрыть произвольную программу.

В чем тут дело и как решить проблему?


Наверх

Титульная страница Поиск, карта сайта Написать письмо