Сейчас на форуме: tyns777, zds, JustLife (+4 невидимых)

 eXeL@B —› Программирование —› Глобальный хук клавиатуры. Как избежать торможения обработки при подвисании?
Посл.ответ Сообщение


Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 01 февраля 2010 20:45
· Личное сообщение · #1

Здравствуйте!

Помогите найти решение проблемы. Суть в следующем:
Есть некая программа которая запускает мою dll. По ходу работы программы я должен подсчитывать точное кол-во нажатий на определённую клавишу, например F9. Для этого решил использовать глобальный хук клавиатуры который отлавливает нажатия даже вне окна программы: hook:=SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardProc, HInstance, 0);
Всё работает хорошо до тех пор, пока программа не задумывается при определённых действиях на пару секунд. В этот момент ловушка порождённая в dll которую подгружает основная программа – замирает… Я понимаю, что программа не должна жрать столько ресурсов, что всё начинает тормозить, но имеем то, что имеем.

Провожу тест, небольшая программа на дельфи при загрузке устанавливает вышеописсаный хук и имеет кнопку которая делает Sleep(5000);
Запускаю две копии, жму F9 –нажатия ловят обе. В первой тестовой программе нажимаю кнопку c паузой, она уже не ловит нажатия, вторая ловит. Теперь нажимаю паузу во второй копии – не ловят обе, это естественно, так как самый верхний по уровню обработчик – это обработчик установленный последним и естественно, что подвисая вторая копия не передаёт обработку по цепочке.

Конечно, как выход можно делать хук во внешней программе и опрашивать её каким либо способом, либо банально создать поток который будет проверять нажатие через GetAsyncKeyState(vk_F9) каждые N миллисекунд, но прежде хочу спросить, может кто знает более красивое решение подобной ситуации (без написания драйвера )?
Внешняя программа – неприлично и гиморно, поток – будет кушать и без того не хватающие ресурсы если проверять будет часто, либо пропустит нажатие если будет проверять реже...



Ранг: 56.1 (постоянный), 9thx
Активность: 0.040
Статус: Участник

Создано: 01 февраля 2010 21:17
· Личное сообщение · #2

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




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 01 февраля 2010 23:16
· Личное сообщение · #3

vptrlx пишет:
но, может быть, поможет что-то вроде вызова SetWindowsHookEx из отдельного потока


Пытаюсь, не срабатывает, видимо нужно правильно указать один из двух последних параметров функции.
Блин, ну в той же длл в отдельном потоке GetAsyncKeyState отлично работает, не пойму почему хук замирает...




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 02 февраля 2010 03:23
· Личное сообщение · #4

ToBad пишет:
отдельном потоке GetAsyncKeyState отлично работает


Вру, в боевых условиях провалилось и это... Не стопорится совсем, но теряет нажатия...

Складывается мнение, что нужно использовать SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardProc, HInstance, 0) в отдельном приложении и взаимодействовать с ним получая результат по мере необходимости.
Вот вопрос какой, может быть можно насунуть этот хук другому приложению, тому же експлореру или винлогону, что бы торможения в ЕХЕ который использует длл не тормозили обработчик?
Чушь конечно сказал, но очень нужны идеи и советы...



Ранг: -4.3 (нарушитель)
Активность: 0.010
Статус: Участник

Создано: 02 февраля 2010 04:45
· Личное сообщение · #5

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



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 02 февраля 2010 06:13
· Личное сообщение · #6

ToBad
Шадов доставляет сообщения в контексте вызывающего его потока. Вы должны отдать управление на NtUserGetMessage/GetMessage(), тогда шадов вызывет свой калбэк для доставки сообщения(apfnDispatch[fnHkINLPMSG]), а далее после возврата в шадов из калбэка произойдёт возврат из сервиса. Зависает потомучто поток висит выполняя некоторые действия, это не допустимо. Следует отвести для обработки оконных сообщений отдельный не загруженный поток.



Ранг: 61.4 (постоянный), 1thx
Активность: 0.020
Статус: Участник

Создано: 02 февраля 2010 06:20
· Личное сообщение · #7

+1.
Хуки дергаются через win32k-колбеки.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 02 февраля 2010 19:50
· Личное сообщение · #8

Спасибо всем за подсказки!
Как я понял отдельный процесс или сервис это наиболее надёжный вариант в этой ситуации?
В общем пока реализовал в виде отдельного приложения с взаимодействием через FileMapping.
Посмотрю как будет вести себя в работе...



Ранг: 61.4 (постоянный), 1thx
Активность: 0.020
Статус: Участник

Создано: 03 февраля 2010 01:15
· Личное сообщение · #9

проще отдельно выделить "оконный" поток.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 03 февраля 2010 02:51
· Личное сообщение · #10

n0name пишет:
проще отдельно выделить "оконный" поток.


А как? Можно какой нибудь пример или статью, желательно не дельфях...
Если бы так заработало, я только за.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 04 февраля 2010 01:40
· Личное сообщение · #11

Может инжектить длл с хуком в какой нибудь процесс?



Ранг: 61.4 (постоянный), 1thx
Активность: 0.020
Статус: Участник

Создано: 04 февраля 2010 01:50
· Личное сообщение · #12

ToBad пишет:
А как? Можно какой нибудь пример или статью, желательно не дельфях...

Рихтера стоит почитать.
Вкратце - скорее всего вполне достаточно GetMessage() в цикле крутить в отдельном потоке.




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 04 февраля 2010 02:03
· Личное сообщение · #13

n0name пишет:
скорее всего вполне достаточно GetMessage() в цикле крутить в отдельном потоке.


Так я GetAsyncKeyState(vk_F9) таким образом курутил и не всегда работало правильно.



Ранг: 61.4 (постоянный), 1thx
Активность: 0.020
Статус: Участник

Создано: 04 февраля 2010 02:15
· Личное сообщение · #14

не стоит сравнивать зеленое с горьким.



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 04 февраля 2010 02:58
· Личное сообщение · #15

ToBad
> Так я GetAsyncKeyState(vk_F9) таким образом курутил и не всегда работало правильно.
Нужно не в ней вращаться, а в GetMessage(), сказали ведь




Ранг: 450.3 (мудрец), 13thx
Активность: 0.20
Статус: Участник

Создано: 04 февраля 2010 19:19 · Поправил: ToBad
· Личное сообщение · #16

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

n0name пишет:
скорее всего вполне достаточно GetMessage() в цикле крутить в отдельном потоке.


Clerk пишет:
Нужно не в ней вращаться, а в GetMessage(), сказали ведь


В смысле так?:
Code:
  1.   while GetMessage(Msg, 0, 0, 0) do
  2.     begin
  3.       TranslateMessage(Msg);
  4.       DispatchMessage(Msg);
  5.     end;

Делал и в длл с хуком которую подгружал, и когда в приложении реализовывал хук, и в отдельном потоке, всё равно тормозится...
Реализовал хук в отдельной длл, подгружаю через loadlibrary - работает но тормозится, решил подгрузить другому процессу через InjectDll (библиотека advApiHook от MS-Rem), инжектил к блокноту, хук вообще не работает...
хз, что за невезуха...


 eXeL@B —› Программирование —› Глобальный хук клавиатуры. Как избежать торможения обработки при подвисании?
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати