1

Тема: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Можно ли с помощью OnMessage() отследить появление новых процессов и отмирание старых?

2

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Нельзя. Подобный мониторинг осуществляется средствами WMI.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Нельзя. Подобный мониторинг осуществляется средствами WMI.

То есть на это нельзя поставить хук (не OnMessage)?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

4

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Во всяком случае, я такого хука не обнаружил.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Во всяком случае, я такого хука не обнаружил.

Печалька.

Подобный мониторинг осуществляется средствами WMI.

Я хотел уточнить термины, если что то осуществляется только средствами WMI, то АНК это уже никак не сможет перехватить?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

6

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Почему же, AHK может пользоваться средствами WMI через COM, здесь уже была куча примеров. Собственно, вот:

#Persistent

OnlyAHK := 0   ; чтобы отслеживать только процессы AutoHotkey.exe — 1, иначе — 0

oSvc := ComObjGet("winmgmts:")
ComObjConnect(createSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessCreate_")
ComObjConnect(deleteSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessDelete_")

Command := "Within 1 Where TargetInstance ISA 'Win32_Process'"
   . (OnlyAHK ? " And TargetInstance.Name = 'AutoHotkey.exe'" : "")
oSvc.ExecNotificationQueryAsync(createSink, "select * from __InstanceCreationEvent " Command)
oSvc.ExecNotificationQueryAsync(deleteSink, "select * from __InstanceDeletionEvent " Command)

ProcessCreate_OnObjectReady(obj)
{
   Process := obj.TargetInstance
   TrayTip, Новый процесс, % "PID = " Process.ProcessID "`nИмя = " Process.Name "`nКомандная строка = " Process.CommandLine
}

ProcessDelete_OnObjectReady(obj)
{
   Process := obj.TargetInstance
   TrayTip, Завершён процесс, % "PID = " Process.ProcessID "`nИмя = " Process.Name "`nКомандная строка = " Process.CommandLine
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

teadrinker
Отлично.

Во всяком случае, я такого хука не обнаружил.

Видимо снова моё непонимание терминов. Сообщение получать можно. Значит я неправильно использовал слово хук в вопросе:?

То есть на это нельзя поставить хук (не OnMessage)?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

8

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Если понимать слово хук (hook), как понимает его Microsoft, то неправильно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

9

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

То есть на это нельзя поставить хук (не OnMessage)?

То есть в данном контексте правильнее спросить:

То есть AutoHotkey неможет получать сообщения о запуске и закрытии процессов?

---
Значит хук это не только извещение о событии, но "и его перехват (блокировка) на пути к адресату"?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

10

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

В данном контексте правильнее спросить "Можно ли отслеживать создание/завершение процессов, используя AHK?". Хук в классическом понимании — это перехват сообщений (Message), а при создании/завершении процессов никаких сообщений не рассылается.
Что же касается хука, устанавливаемого посредством SetWinEventHook(), это немного отдельная тема, он действительно отслеживает именно события (без возможности перехвата), но в списке событий такого нет.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

11 (изменено: serzh82saratov, 2013-10-20 18:06:51)

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Ещё один, наверняка глупый вопрос:

Можно ли отслеживать создание/завершение процессов

...

а при создании/завершении процессов никаких сообщений не рассылается.

В чём отличие понятий - "отслеживать событие" и "получать сообщения о событии"?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

12

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Отслеживать — получать информацию о сообщениях (или перехватывать их), отправленных окнам чужих процессов, а получать можно сообщения, отправленные окнам своего процесса. "Сообщение о событии" — это неясный термин, есть просто сообщения, несущие какую-то информацию.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

13

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

teadrinker
Понял. Спасибо за ЛикБез

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

14

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

teadrinker пишет:

Почему же, AHK может пользоваться средствами WMI через COM, здесь уже была куча примеров. Собственно, вот:

#Persistent

OnlyAHK := 0   ; чтобы отслеживать только процессы AutoHotkey.exe — 1, иначе — 0

oSvc := ComObjGet("winmgmts:")
ComObjConnect(createSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessCreate_")
ComObjConnect(deleteSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessDelete_")

Command := "Within 1 Where TargetInstance ISA 'Win32_Process'"
   . (OnlyAHK ? " And TargetInstance.Name = 'AutoHotkey.exe'" : "")
oSvc.ExecNotificationQueryAsync(createSink, "select * from __InstanceCreationEvent " Command)
oSvc.ExecNotificationQueryAsync(deleteSink, "select * from __InstanceDeletionEvent " Command)

ProcessCreate_OnObjectReady(obj)
{
   Process := obj.TargetInstance
   TrayTip, Новый процесс, % "PID = " Process.ProcessID "`nИмя = " Process.Name "`nКомандная строка = " Process.CommandLine
}

ProcessDelete_OnObjectReady(obj)
{
   Process := obj.TargetInstance
   TrayTip, Завершён процесс, % "PID = " Process.ProcessID "`nИмя = " Process.Name "`nКомандная строка = " Process.CommandLine
}

А интересный код. К сожалению, я не знаю о существовании каких-либо туториалов (даже на английском) по работе с WMI, с COM и с объектами (про работу с объектами есть обычная документации, но она не изобилует примерами и после её тщательного прочтения - я ничего не понял) в AHK, потому прошу ещё помочь.

+ полная версия объяснения проблемы

Я все эти вопросы задаю с целью улучшить работу своего MasterScript скрипта, который сейчас работает таким образом:
есть label (вызываемый периодически, по таймеру) который содержит For Process In ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process"), которая наполняет 2 массива данными: 1 для информации обо всех процессах, 1 для информации только о запущенных ahk-скриптах.

Зачем мне нужны эти массивы? Коротко объяснить не получится, надо сначала рассказать что дальше делает скрипт с этими данными:

Затем из "скриптового" массива собираются PIDы всех процессов в 1 однострочную переменную, где все PIDы отделены друг от друга трубой "|".
Эта переменная каждый раз бэкапится и потом производится сравнение текущей "свежей" версии этой переменной с её бэкапом.
При этом выявляется разницу между ними (появились ли новые PIDы? умерли ли какие-то из старых PIDов?).
По этой выявленной разнице скрипт принимает решение обновлять ли ListView со списком запущенных скриптов, и если обновлять, то - как это сделать? (нужно ли удалить какие-то строки? если да, то какие? нужно ли добавить новых строк? если да, то с каким содержимым?)
В случае с удалением строк - проблем нет, а вот в случае с добавлением новых - информация об их содержимом как раз и берётся из "скриптового" массива.

В принципе, на этом этапе мне уже "скриптовый" массив и не нужен, если я буду брать информацию из твоей функции ProcessCreate_OnObjectReady(obj), с этим я определился.

Тут проблема с другим массивом: "общепроцессный" массив нужен для работы фичи "Process Assistant" (про работу этой фичи рассказано в теме моего скрипта) и мне нужно, чтобы этот массив всегда содержал актуальную информацию, т.е. чтобы твои функции ProcessDelete_OnObjectReady(obj) и ProcessCreate_OnObjectReady(obj) соответствующим образом обновляли этот массив.

Как в таком случае правильно переписать функции ProcessDelete_OnObjectReady(obj) и ProcessCreate_OnObjectReady(obj), чтобы они обновляли существующий массив со списком данных обо всех процессах?
Массив многомерный: состоит из [index, "pid"] := Process.ProcessId и [index, "exe"] := Process.ExecutablePath.
Ключевое поле в массиве - связка [index, "pid"] процесса.
Если это удобней делать не массивами, а объектами (хотя и массивы, вроде бы, - это частный случай объектов) - покажи, пожалуйста, как их наполнять и как с ними работать (получать содержимое определённой ячейки).

+ tl;dr версия проблемы

как правильно переписать функции ProcessDelete_OnObjectReady(obj) и ProcessCreate_OnObjectReady(obj), чтобы они обновляли существующий массив со списком данных обо всех процессах?
Массив многомерный: состоит из [index, "pid"] := Process.ProcessId и [index, "exe"] := Process.ExecutablePath.
Ключевое поле в массиве - связка [index, "pid"] процесса.
Если это удобней делать не массивами, а объектами (хотя и массивы, вроде бы, - это частный случай объектов) - покажи, пожалуйста, как их наполнять и как с ними работать (получать содержимое определённой ячейки).

15

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Не совсем ясна суть вопроса. Если ты знаешь, как получить PID и ExecutablePath, то в чём проблема занести/удалить их в свой массив?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

16

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Проблема более не актуальна.
Я плохо умел работать с массивами, но сейчас, вроде, стал получше понимать работу объектов.

17

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

teadrinker, возник новый вопрос по предложенному тобой коду:
если я убиваю/запускаю пачку процессов сразу, то как работают эти функции (ProcessCreate_OnObjectReady и ProcessDelete_OnObjectReady)? Судя по тому, что ни одно из сообщений не пропускается - я предполагаю, что существует какая-то очередь, где они дожидаются момента, когда скрипт их обработает. Так ли это?
Я повесил во внутрь этих функций вызов другой функции, которая парсит массивы и делает кучу сравнений, обновляет массивы и список (ListView) и т.п. и я боюсь, что при объёмных массивах на всё это будет уходить достаточно много времени.
Во-первых, я боюсь, что это вызовет какие-то конфликты, т.к. я не знаю в какой из моментов начинает обрабатываться следующий вызов ProcessCreate_OnObjectReady или ProcessDelete_OnObjectReady из существующей очереди.
Во-вторых, вызов этой функции (которая парсит массивы и т.п.) - в любом случае лучше бы делать не каждый раз, при обработке вызовов ProcessCreate_OnObjectReady/ProcessDelete_OnObjectReady, а один раз спустя секунду после обработки последнего из всей пачки этих вызовов. Т.е. если в течение секунды с момента обработки предыдущего вызова - появляется новый, то таймер надо заново "завести" на ожидание секунды уже с момента этого вызова и т.д.
Можно ли это как-то сделать? Как?
Просто не хочется заводить постоянный таймер с выполнением периодических проверок.

Как идея по поводу того, как это реализовать у меня есть только такое:
добавить в во внутрь ProcessCreate_OnObjectReady и ProcessDelete_OnObjectReady

thisTime := A_Now 
SetTimer, timer, 500

и отдельно создать ярлык примерно следующего содержания для вызова этим таймером:

timer:
if (thisTime+500 < A_Now)
     sleep 500
Else
     funcCall()
SetTimer, timer, off
Return

Но я не уверен, что во время этого Sleep 500 скрипт не будет вообще приостановлен, а сможет обрабатывать очередь вызовов тех функций.

Или это делается иначе? Признаться, я не до конца понимаю как работает пример 3 из справки, но на вид - это как раз аналогично моей проблеме.

Может Critical тут как-то поможет?

18

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Вроде научился правильно использовать Critical.
Но вот новый вопрос:
у меня на появление 1 нового процесса ProcessCreate_OnObjectReady() срабатывает несколько раз.
Аналогичная проблема с WM_DEVICECHANGE() решилась добавкой фильтрации по hwnd (т.е. он ловил и аналогичные сообщения, которые отправлялись чужим окнам (чужих приложений)), а как здесь добавить аналогичную фильтрацию?

19

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Drugoy пишет:

у меня на появление 1 нового процесса ProcessCreate_OnObjectReady() срабатывает несколько раз.

Приведите минимальный код, который демонстрирует проблему, у меня срабатывает как положено, один раз на каждый процесс.

Аналогичная проблема с WM_DEVICECHANGE() решилась добавкой фильтрации по hwnd (т.е. он ловил и аналогичные сообщения, которые отправлялись чужим окнам (чужих приложений))

Нет, такого не было. OnMessage() отлавливает только сообщения, посланные окнам своего процесса.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

20

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

teadrinker пишет:

Нет, такого не было. OnMessage() отлавливает только сообщения, посланные окнам своего процесса.

А, точно-точно. Там немножко другой нюанс был: там сообщения дублировались из-за того, что у моего скрипта не одно, а несколько окон и сообщение отправляется каждому окну.
Исправили тогда это всё заменой WM_DEVICECHANGE(wp, lp) на WM_DEVICECHANGE(wp, lp, msg, hwnd) + проверкой if (hwnd = A_ScriptHwnd).

Касательно минимального кода - увы, это очень проблематично, но я в функцию ProcessCreate_OnObjectReady(Obj){} добавил Process := obj.TargetInstance + outputdebug, % Process.ExecutablePath и вижу, что при однократном запуске одного скрипта - функция вызывается трижды. У меня в скрипте как раз 3 окна: иконка в трее, основное GUI окно и дополнительное GUI окно.

21

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

У меня в скрипте как раз 3 окна: иконка в трее, основное GUI окно и дополнительное GUI окно.

А причём тут иконка в трее?


#NoTrayIcon
DetectHiddenWindows on
WinGet, hwnd, List, % "ahk_pid " DllCall("GetCurrentProcessId")
Loop % hwnd
{
    WinGetClass, Class, % "ahk_id" hwnd%A_Index% 
    WinGetTitle, Title, % "ahk_id" hwnd%A_Index% 
    MsgBox % Title "`n" Class
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

22

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

serzh82saratov, я и с этим ошибся, но по большому счёту это и не важно. Не иконка в трее, а просто у любого процесса есть своё встроенное окно. + доп. окна создаются если использовать, например gdi+ полотна (без привязки к каким-то окнам).
Вопрос в том как бы отфильтровать, дублирующиеся сообщения у вышеобозначенной функции? На MSDN поискал - но ничего не понял / не нашёл / вроде как нашёл, что у этой функции нет аттрибута hwnd. Help!

23

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

К количеству окон у процесса этот метод не имеет отношения.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

24

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Чего-то я очень не внимательный. Визуально текст оказался похожим, а на самом деле это разные оповещения были от разных функций (имена длинные и визуально похожие). Всё срабатывает однократно, извините за беспокойство.

25

Re: AHK: можно ли исп-ть OnMessage() для отслеживания процессов?

Я долго не мог понять почему у меня в скрипте в обновляемом списке где должны отображаться только живые процессы - собирались и "зомби", пока не начал отладку. Оказалось, что дело в этом куске кода:

teadrinker пишет:
ProcessDelete_OnObjectReady(obj)
{
   Process := obj.TargetInstance
   TrayTip, Завершён процесс, % "PID = " Process.ProcessID "`nИмя = " Process.Name "`nКомандная строка = " Process.CommandLine
}

В этой функции я добавил вывод отладочной информации (.processID, .commandLine и .executablePath процессов) через Outputdebug.
Оказалось, что в некоторых случаях при смерти процессов ahk-скриптов (у которых при запуске были заполнены все данные: и .processID, и .commandLine, и .executablePath) почему-то .commandLine и .executablePath становятся пустыми.

Такое происходит не всегда, довольно редко, с одними и теми же скриптами, с которыми в другие разы всё ок. Закономерностей и взаимосвязей этого явления с чем-либо не обнаружил.