Получение событий, что "чужие" окна создаются, закрываются
От: Аноним  
Дата: 31.07.13 22:19
Оценка: :))
Нужно в .NET приложении делать некоторые вещи при создании/закрытии "чужих" окон. Должно работать на основных версиях Windows — от XP и выше

Из дот нета напрямую нельзя устанавливать глобальные хуки для получения соответсвующих событий, нужно выносить эти вызовы в стороние неуправляемые библиотеки.
Я попробовал использовать "GlobalCbtHook.dll" из демо-проекта на codeproject:
http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H (Using Window Messages to Implement Global System Hooks in C#)
На XP работает, но на Win8 уже нет. Разбираться с "с-кодом" большого желания нет, хотелось бы уложиться в рамки управляемого кода.


Где то на одном форуме вычитал что для этого можно использовать WMI, подобно этому посту:
http://weblogs.asp.net/whaggard/archive/2006/02/11/438006.aspx (Using WMI to monitor process creation, deletion and modification in .NET)
Но здесь можно наблюдать за создание процессов, а мне нужны окна. Может быть даже получится обойтись лишь родительскими, те что в менеджере задач как приложения определяются. Можно ли их из процессов отфильтровать?

Может быть есть другие способы?
Re: Получение событий, что "чужие" окна создаются, закрываются
От: Аноним  
Дата: 01.08.13 09:47
Оценка:
drol, не понимаю, почему весело?
Re: Получение событий, что "чужие" окна создаются, закрываются
От: SaZ  
Дата: 01.08.13 10:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может быть есть другие способы?


Для начала: http://www.rsdn.ru/forum/info/FAQ.dotnet.hooks
Re[2]: Получение событий, что "чужие" окна создаются, закрываются
От: Аноним  
Дата: 01.08.13 12:07
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, Аноним, Вы писали:


А>>Может быть есть другие способы?


SaZ>Для начала: http://www.rsdn.ru/forum/info/FAQ.dotnet.hooks


Уже пробовал, не работают. Из c# можно ставить лишь некоторые хуки:

Global hooks are not supported in the .NET Framework

Except for the WH_KEYBOARD_LL low-level hook and the WH_MOUSE_LL low-level hook, you cannot implement global hooks in the Microsoft .NET Framework. To install a global hook, a hook must have a native DLL export to inject itself in another process that requires a valid, consistent function to call into. This behavior requires a DLL export. The .NET Framework does not support DLL exports. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically.

Low-level hook procedures are called on the thread that installed the hook. Low-level hooks do not require that the hook procedure be implemented in a DLL.


Взято здесь: http://support.microsoft.com/kb/318804
Re[3]: Получение событий, что "чужие" окна создаются, закрываются
От: Sinatr Германия  
Дата: 02.08.13 06:44
Оценка:
Здравствуйте, Аноним, Вы писали:

Можно попробовать создать очень маленькую нативную либу (на C++ например), форвардющую эвенты. Хранить в ресурсах например.
---
ПроГLамеры объединяйтесь..
Re[4]: Получение событий, что "чужие" окна создаются, закрываются
От: Аноним  
Дата: 02.08.13 21:25
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


S>Можно попробовать создать очень маленькую нативную либу (на C++ например), форвардющую эвенты. Хранить в ресурсах например.


Хотел бы оставаться в рамках c#, к тому же использую Express VS с единственным языком. Хотя, кажется, я уже натолкнулся на возможное решение, тестовый проектик работает.
SetWinEventHook. http://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx

Нужно только фильтровать необходимые события и определять от кого пришло сообщение, т.к сообщения приходят также от ряда контролов.
Для это использую GetWindowInfo:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633516(v=vs.85).aspx
и проверяю значения Style
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx

Попутный вопрос: как по хвнд лучше всего определить, окно ли это? А то со стилями не очень удобно, не понятно что считать окном.
ЗЫ. Окном считается все видимые окна, к ним относятся, например, и диалоговые окна и MessageBox-окна. Не интересуют MDI окна.
Re: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 04.08.13 12:23
Оценка: -1
Здравствуйте, Аноним, Вы писали:

А>На XP работает, но на Win8 уже нет. Разбираться с "с-кодом" большого желания нет, хотелось бы уложиться в рамки управляемого кода.


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

В управляемом коде хук невозможен, так как хук вызывается операционной системой, а Windows написана не на управляемом коде.
With best regards
Pavel Dvorkin
Re[5]: Получение событий, что "чужие" окна создаются, закрываются
От: Sinatr Германия  
Дата: 05.08.13 07:05
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Попутный вопрос: как по хвнд лучше всего определить, окно ли это? А то со стилями не очень удобно, не понятно что считать окном.

А>ЗЫ. Окном считается все видимые окна, к ним относятся, например, и диалоговые окна и MessageBox-окна. Не интересуют MDI окна.

Совсем забыл уже WinAPI, там есть Parent'ы? Если парент есть, то контрол (или мди чилд окно, или модал с парентом? гмм), иначе — окно.
---
ПроГLамеры объединяйтесь..
Re[5]: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 05.08.13 07:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Попутный вопрос: как по хвнд лучше всего определить, окно ли это? А то со стилями не очень удобно, не понятно что считать окном.


Если есть hWnd, то это окно по определению. так как hWnd — хендл окна.
With best regards
Pavel Dvorkin
Re[6]: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 05.08.13 07:12
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Совсем забыл уже WinAPI, там есть Parent'ы?


Есть.

>Если парент есть, то контрол (или мди чилд окно, или модал с парентом? гмм), иначе — окно.


Чайлды тоже окна. Parent не имеют overlapped окна и popup без parent (popup могут быть и с parent, и без). Чайлды всегда имеют parent. MDI children тоже имеют.
With best regards
Pavel Dvorkin
Re[6]: Получение событий, что "чужие" окна создаются, закрываются
От: Аноним  
Дата: 05.08.13 12:50
Оценка:
PD>Если есть hWnd, то это окно по определению. так как hWnd — хендл окна.


Из документации к SetWinEventHook, событие EVENT_OBJECT_CREATE:
An object has been created. The system sends this event for the following user interface elements: caret, header control, list-view control, tab control, toolbar control, tree view control, and window object. Server applications send this event for their accessible objects.
Before sending the event for the parent object, servers must send it for all of an object's child objects. Servers must ensure that all child objects are fully created and ready to accept IAccessible calls from clients before the parent object sends this event.

Де-факто, при запуске калькулятора, получаю десятки событий для каждой кнопочки отдельно.
По хендлу извлекаю информацию при помощи GetWindowInfo() для каждой этой кнопочки.
По-моему понятие окна здесь несколько шире.
Re[7]: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 05.08.13 13:40
Оценка: +1
Здравствуйте, Аноним, Вы писали:


PD>>Если есть hWnd, то это окно по определению. так как hWnd — хендл окна.



А>Из документации к SetWinEventHook, событие EVENT_OBJECT_CREATE:

А>An object has been created. The system sends this event for the following user interface elements: caret, header control, list-view control, tab control, toolbar control, tree view control, and window object. Server applications send this event for their accessible objects.
А>Before sending the event for the parent object, servers must send it for all of an object's child objects. Servers must ensure that all child objects are fully created and ready to accept IAccessible calls from clients before the parent object sends this event.

А>Де-факто, при запуске калькулятора, получаю десятки событий для каждой кнопочки отдельно.

А>По хендлу извлекаю информацию при помощи GetWindowInfo() для каждой этой кнопочки.
А>По-моему понятие окна здесь несколько шире.

Понятие окна в Windows строго определено : окно — это все, что имеет hWnd. Равно как и наоборот — все, что не имеет hWnd, не есть окно, даже если выглядит как окно (т.н. windowsless controls, например, в WPF)

Событий при использовании SetWinEventHook может быть много, в описании функции приведены типы event'ов.

Ловить для задачи ТС надо не с помощью SetWinEventHook, а просто с помощью SetWindowsHookEx, фильтры

WH_CBT/HCBT_CREATEWND и WH_CBT/HCBT_DESTROYWND (вот-вот будет создано/уничтожено)

или

WH_SHELL/HSHELL_WINDOWCREATED и WH_SHELL/HSHELL_WINDOWDESTROYED (только что создано/уничтожено)

Последний хук, кстати, работает только при создании/уничтожении top-level windows, то есть не имеющих parent
With best regards
Pavel Dvorkin
Re[2]: вопрос к drol
От: Pavel Dvorkin Россия  
Дата: 05.08.13 13:43
Оценка:
Если не секрет, с чем не согласен — с тем, что можно было давно сделать нативный хук или с тем, что нельзя сделать windows hook в управляемом коде ?
Если первое — можешь не отвечать. Если второе — дай ссылку, как его сделать на управляемом коде.
With best regards
Pavel Dvorkin
Re[2]: Получение событий, что "чужие" окна создаются, закрываются
От: drol  
Дата: 06.08.13 12:10
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>В управляемом коде хук невозможен, так как хук вызывается операционной системой, а Windows написана не на управляемом коде.


"Управляемость" не имеет никакого отношения к вопросу. Никаких особых технических проблем в предоставлении удобного взаимодействия .NET и SetWindowsHookEx API нет. Просто данный конкретный вид interop'а в CLR не был реализован.
Re[3]: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 06.08.13 13:04
Оценка: :)
Здравствуйте, drol, Вы писали:

D>"Управляемость" не имеет никакого отношения к вопросу. Никаких особых технических проблем в предоставлении удобного взаимодействия .NET и SetWindowsHookEx API нет. Просто данный конкретный вид interop'а в CLR не был реализован.


Разумеется, сделать interop-обертку над SetWindowsHookEx можно, но как с самой функцией хука-то быть ?



HHOOK SetWindowsHookEx(int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);


HOOKPROC lpfn — указатель на функцию, которая будет вызвана из нативного кода (из kernel32.dll, я полагаю), и должна быть написана на нативном коде, так как вызывающий ее код вызывает ее путем соответствующих машинных команд (push, call/jmp). Как им образом можно подставить сюда функцию(метод etc.) на управляемом коде ?

Ну и напомню, что для глобальных хуков (не всех) хуковая функция должна быть в DLL, а DLL будет внедрена в адресное пространство другого процесса. Хочешь ли ты сказать, что в процесс, который и слышать про дотнет ничего не слышал, можно внедрить кусок управляемого кода ?
With best regards
Pavel Dvorkin
Re[4]: Получение событий, что "чужие" окна создаются, закрываются
От: drol  
Дата: 06.08.13 15:43
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>для глобальных хуков (не всех) хуковая функция должна быть в DLL, а DLL будет внедрена в адресное пространство другого процесса.


Вот этот момент и требует специальной поддержки в CLR. Реализовать можно кучей способов. Например, CLR могла бы на ходу строить DLL со всей необходимой обвязкой.

PD>Хочешь ли ты сказать, что в процесс, который и слышать про дотнет ничего не слышал, можно внедрить кусок управляемого кода ?


Кусок — нельзя. Внедрить можно CLR. Которая и будет исполнять всё что надо и душе угодно.
Re[4]: Получение событий, что "чужие" окна создаются, закрываются
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 06.08.13 19:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>HOOKPROC lpfn — указатель на функцию, которая будет вызвана из нативного кода (из kernel32.dll, я полагаю), и должна быть написана на нативном коде, так как вызывающий ее код вызывает ее путем соответствующих машинных команд (push, call/jmp). Как им образом можно подставить сюда функцию(метод etc.) на управляемом коде ?


Marshal.GetFunctionPointerForDelegate
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[5]: Получение событий, что "чужие" окна создаются, закрываются
От: Pavel Dvorkin Россия  
Дата: 07.08.13 02:31
Оценка: -1
Здравствуйте, drol, Вы писали:


D>Вот этот момент и требует специальной поддержки в CLR. Реализовать можно кучей способов. Например, CLR могла бы на ходу строить DLL со всей необходимой обвязкой.

D>Кусок — нельзя. Внедрить можно CLR. Которая и будет исполнять всё что надо и душе угодно.

В теории ты прав, конечно — в принципе сделать можно все, что угодно. Практически же внедрение рантайма дотнета в неуправляемый процесс ради хуков — гм, я даже не берусь оценить , сколько и каких проблем это может вызвать... Так что хуки останутся в неуправляемом коде.
With best regards
Pavel Dvorkin
Re[6]: Получение событий, что "чужие" окна создаются, закрываются
От: drol  
Дата: 13.08.13 14:04
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>В теории ты прав,


Ещё смешней. Это самая что ни на есть практика. Вот, например, managed in-process COM server: COM Interop Part 2: C# Server Tutorial

Делается на счёт раз. И всё работает прямо из коробки.

*Всегда поражала тупизна C++ IntelliSense в Visual Studio. Добавляем директиву импорта .tlb, так пока проект не переоткроешь он матерится, что не может найти объявленные в ней типы\данные

PD> Практически же внедрение рантайма дотнета в неуправляемый процесс


См. выше. Вся основная механика уже давным-давно имеется, причём автоматическая. Она была создана для реализации COM interop. Никаких особых проблем с инжектингом CLR в произвольный процесс нет. Как я уже говорил, Microsoft поленилась сделать обвязку по части генерации DLL для хуков. И, в принципе, поступила правильно. Бо накалякать её руками дело пары часов.
Re[4]: Получение событий, что "чужие" окна создаются, закрываются
От: TK Лес кывт.рф
Дата: 14.08.13 06:05
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Разумеется, сделать interop-обертку над SetWindowsHookEx можно, но как с самой функцией хука-то быть ?

PD>Ну и напомню, что для глобальных хуков (не всех) хуковая функция должна быть в DLL, а DLL будет внедрена в адресное пространство другого процесса. Хочешь ли ты сказать, что в процесс, который и слышать про дотнет ничего не слышал, можно внедрить кусок управляемого кода ?

Тут следует, что если хук не надо внедрять в другой процесс, то он может быть целиком на managed коде.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.