Можно ли определить, когда Windows-клавиатура автоматически отключила хук низкоуровневой клавиатуры? - PullRequest
8 голосов
/ 18 июля 2011

Я работаю над программой, которая использует зацепки клавиатуры.Однако, когда ПК, на котором запущена программа, немного перегружен, это приводит к тому, что Windows отключает хук от программы, в результате чего он перестает отвечать на нажатия клавиш.или, что еще лучше, предложите другой способ решения точно такой же проблемы, используя другую архитектуру, возможно, с использованием конвейера?

Ответы [ 4 ]

16 голосов
/ 18 июля 2011

Вы не можете «обнаружить» это, и вам абсолютно не нужно это делать. То, что вы описываете, - это функция, в частности, представленная в Windows 7 для защиты вашей системы от мошеннических приложений.

Применимая документация описывает это так (обратите особое внимание на выделенную шрифт секцию):

Процедура подключения должна обработать сообщение за меньшее время, чем запись данных, указанная в значении LowLevelHooksTimeout в следующем разделе реестра:

HKEY_CURRENT_USER\Control Panel\Desktop

Значение указывается в миллисекундах. Если процедура перехвата завершается, система передает сообщение следующему перехватчику. Однако в Windows 7 и более поздних версиях ловушка удаляется без вызова. Приложение не может узнать, снят ли хук.

Решение здесь, скорее всего, , а не , чтобы выяснить способ «обнаружить», когда хук удален, и переустановить его. Вы должны были понять, что вы делаете что-то не так, когда операционная система удаляет хук в first time.

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

Фактически, это почти точно , что продолжает предлагать документация:

Примечание: Ловушки отладки не могут отследить этот тип низкоуровневых хуков клавиатуры. Если приложение должно использовать низкоуровневые хуки, оно должно запускать хуки в выделенном потоке, который передает работу рабочему потоку, а затем немедленно возвращается. В большинстве случаев, когда приложению необходимо использовать низкоуровневые хуки, оно должно вместо этого контролировать необработанный ввод. Это связано с тем, что необработанный ввод может асинхронно отслеживать сообщения мыши и клавиатуры, предназначенные для других потоков, более эффективно, чем перехватчики низкого уровня. Для получения дополнительной информации о необработанном вводе см. Исходный ввод .

3 голосов
/ 10 августа 2012

Я не уверен, что всегда виноват крюк клавиатуры. Кажется, мы все согласны с тем, что в идеальных или средних условиях все должно быть отзывчивым. Но в течение всего срока службы от запуска до выключения крючок также должен выдерживать некоторые наихудшие сценарии. В моей компании мы написали несколько клавиатурных хуков, они настолько легковесны и асинхронны, насколько это возможно, но иногда они по-прежнему отключаются.

Как пользователь, я каждый день набираю несколько десятков тысяч символов. В лучшем случае я перезагружаюсь раз в месяц, а иногда я пропускаю обновление Windows. С такими опциями, как приостановка и спящий режим, я не думаю, что я один. Как разработчик, я должен убедиться, что ловушка продолжает работать от начала до конца, независимо от того, что происходит с системой.

Обычно моя система очень отзывчива. Но могут быть короткие, исключительные моменты, когда он стоит на коленях до такой степени, что даже Windows Aero отключается. Прямо сейчас это очень быстро. Но если я нажму кнопку «Показать рабочий стол», мышь остановится хотя бы на секунду, пока все мои 65 открытых окон свернуты. Что если я нажму клавишу во время одного из этих моментов?

Если Windows может заморозить мышь на одну секунду, если Windows может даже отключить Aero в течение короткого момента большой нагрузки, почему нельзя позволить клавиатуре пережить подобное исключительное время перегрузки? Вместо этого, из-за одного исключительного момента, Windows отключается, незаметно влияя на оставшийся вычислительный процесс до выключения системы. В течение 200 мс, влияющих только на одно нажатие клавиши из тысяч, которые мы нажимаем каждый день, всего за долю секунды я, пользователь, должен перезагрузить систему, потому что, как я понимаю, это единственный способ вернуть макрос клавиатуры или любую другую утилиту Я зависим от моей продуктивной работы.

Даже если было гарантировано предотвратить вышеперечисленное (что, как представляется, наихудший опыт подсказывает, что это не так), я не уверен, что все можно легко сделать в отдельном потоке. Например, предположим, что пользователь устанавливает горячую клавишу для запуска приложения. Не может ли быть причины для запуска приложения из текущего контекста (приоритетное окно, привилегии и т. Д.)? И разве не было бы разумно, чтобы пользователь действительно ожидал и принял задержку, потому что он знает, что, используя клавиатуру, он просто запустил что-то, что занимает больше времени? Я не знаю, является ли пример технически обоснованным, но я хотел показать, как иногда вещи, которые в противном случае могут быть неприемлемыми, могут быть приемлемыми в результате известного события.

Перехваты клавиатуры могут быть очень полезны для многих вещей, от макросов до исправления ошибок и запуска, и такое поведение, представленное в Windows 7, ставит хорошие и плохие, приемлемые и неприемлемые, средние и исключительные значения в той же корзине. Это вредит как пользователям, так как качественные зацепы клавиатуры могут быть убиты, так и разработчикам. Только представьте, что это за кошмар поддержки, когда у вас нет официального решения для вашего приложения, работающего нормально в нормальных условиях, но которое может быть случайно убито при каких-то тяжелых (или других необъяснимых) обстоятельствах.

В заключение, кто-нибудь знает, какой статус у Windows 8, что-нибудь изменилось?

2 голосов
/ 08 февраля 2012

Ответ Коди Грэя превосходен, но FWIW, и исключительно для целей тестирования , вы сможете обнаружить отсоединенный хук.

Когда вызывается ваш обработчик ловушек, сохраните текущее количество тиков в переменной, доступной для основного потока.В основной ветке периодически звоните GetLastInputInfo.Это даст вам счетчик тиков для последнего входного события в системе (а не только в вашем процессе).Если значение, предоставленное GetLastInputInfo, значительно позже (новее), чем ваш последний счет тиков ловушки, можно предположить, что ловушка была отключена.

0 голосов
/ 18 июля 2011

Я думаю, что в вашем хуке есть какой-то "неэффективный" код. это причина, почему делает небольшую перегрузку.

"это заставляет Windows отключить хук от программы"

Возникает ли какая-либо ошибка в вашем хуке, и вы ее не обрабатываете?

AFAIK, Windows не отключит хук, если он сам по себе работает хорошо.

...