![]() |
|
Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply |
![]()
|
|
| ldr12 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
Столкнулся со следующей проблемой.
Создаю с помощью CreateThread() поток, в котором впоследствии вызываю установку хука при помощи SetWindowsHookEx с параметром WH_JOURNALRECORD. За установкой хука следует стандартный цикл обработки очереди сообщений потока GetMessage/TranslateMessage/DispatchMessage. Проблема в том, что если хук ставится в главном потоке процесса, при отсутствии иных запущенных потоков - все работает превосходно. Если же до/после установки хука создается другой поток - все намертво зависает до нажатия Ctrl+Alt+Del. Пробовал блокирующий GetMessage заменять неблокирующим PeekMessage - все то же самое - данная функция виснет намертво. Перепробовал все возможные параметры CreateThread/SetWindowsHookEx/GetMessage - к должному результату не привело. Либо все виснет, либо не работает хук. Опытным путем установил, что если между SetWindowsHookEx и GetMessage/PeekMessage поставить вызов MessageBox, который закрывается потом обычным щелчком мыши или нажатием Enter - то GetMessage начинает работать как ни в чем ни бывало и все потоки функционируют нормально. Напрашивается мысль, что GetMessage необходимо в самом начале работы некое сообщение, вроде щелчка мыши или нажатия клавиши, адресованной вызывающему потоку? Пробовал вставлять туда keybd_event(), mouse_event(), Sleep() - не помогает. Да и почему же тогда работает в главном потоке, и чем мешает хуку запуск дочерних потоков? Что здесь можно сделать? |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
ldr12, отвечу, как принято отвечать в таких случаях: "у тебя ошибка в 17 строке!"
пара вопросов: 1) нигде не упоминается о dll... 2) зачем в потоке цыкл выборки сообщений? от кого их ждет? GetMessage в потоке остановит его выполнение до их появления -------------------- There are always someone smarter than you... |
|||
|
||||
| ldr12 |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
Дело не в наличии/отсутствии ошибок. Я интересуюсь самой сутью зависания, а повторить сей эксперимент может каждый.
1) WH_JOURNALRECORD/WH_JOURNALPLAYBACK хуки не нуждаются в DLL. Об этом написано даже в Remarks разделе соответствующей статьи MSDN. 2) GetMessage останавливает всё вообще. Сообщение не обрабатывается им, не поступает хуку, соответственно хук не может вызвать CallNextHookEx() и позволить другим приложениям эти сообщения обработать. Зачем? А как в таком случае callback-функция хука будет получать извещения о WM_KEYDOWN или WM_LBUTTONDOWN? Есть сообщения окнам, есть сообщения потокам, в случае хуков действует второй вариант. Приведу свой код в упрощенном виде для понятности:
Выяснил одну детальку: если между SetWindowsHookEx и циклом поставить
то ОДИН раз все запустится нормально. Если второй, третий, четвертый раз попробовать - будет снова виснуть. Если же на пятый раз заменить ThHandle на GetCurrentThread, СНОВА запустится нормально. Но на 6, 7, n+1 снова будет виснуть. И так до перезагрузки. Такое ощущение, что как будто бы не освобождаются какие-то уникальные ресурсы, выделяемые моему приложению... Хотя перед завершением работы программы делаю UnhookWindowsHookEx(Hook) и поток мирно завершается. Это сообщение отредактировал(а) ldr12 - 9.2.2007, 17:45 |
||||
|
|||||
| ldr12 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
PostThreadMessage говорит ERROR_INVALID_THREAD_ID. Что, согласно MSDN случается в следующих случаях (Windows 2000):
1) Для потока не было создано очереди сообщений, что исключается, ибо SetWindowsHookEx был успешно вызван. Да и система бы не висела, не сработай он 2) Поток назначения не принадлежит десктопу или процессу потока отправления, что тоже не так, потому что поток сам из себя шлет сообщение. 3) Если указан неверный хендл потока, что тоже не так, потому что ThHandle - реальный идентификатор потока с правами THREAD_ALL_ACCESS, а в случае с GetCurrentThread (псевдоидентификатором, действительным для текущего потока) не помогает и DuplicateHandle, которым пытаюсь получить реальный. |
|||
|
||||
| MetalFan |
|
||||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
согласен. подзабыл слегка) полный бред) в коде куча недочетов. 1) нигде не анализируются резултаты работы функций. 2) зачем TranslateMessage, если не анализируется пользовательский ввод? 3) зачем CreateThread? не лучше ли BeginThread? 4) ThreadProc выглядит как function ThreadProc(Param: integer): Integer; 5) ошибка при установке хука. если устанавоивается хук, с функцией-ловушкой в теле приложения, а не библиотеки, то нужно hMod указать nil, а dwThreadId - id потока, с которым оне ассоциировано.
-------------------- There are always someone smarter than you... |
||||
|
|||||
| ldr12 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
1) Вот и славно, я тебе напомнил
2) Не бред, я все описал - GetMessage зависает и хук не получает сообщения, соответственно не может передать его дальше по цепочке хуков системы и ввод от пользователя просто блокируется, как при BlockInput() 3) Насчет недочетов. 1. Результаты работы функций сто раз мною анализировались за последние сутки и на основании их сделаны вышеизложенные выводы 2. Анализируется именно пользовательский ввод. В т.н. JOURNAL как раз записываются все действия пользователя, ибо применяется он в основном для записи макросов. В любом случае, TranslateMessage тут ни при чем, хотя бы потому, что зависает на самом первом GetMessage. 3.
Лишние усложнения и привязки к RTL ни к чему, да и на код не влияют. Все равно вызывается тот же самый CreateThread, да и параметры все без особых изменений. 4. SizeOf(Integer) = SizeOf(Pointer) = 4, для системы разницы нет, а результат ThreadProc в WinAPI - такая же необязательная вещь, как всякие LParam и WParam в callback процедурах. Справедливости ради замечу, что тестировал все варианты 5. Здесь тонкости перевода Все вышепредложенные идеи протестировал, на всякий случай. Должного рез-та не принесло. Так что пока мы с тобой толчем воду в ступе Рекомендую вышеуказанный код сохранить, скомпилировать, заменив нижний комментарий на WaitForSingleObject() или Sleep(INFINITE) и посмотреть, что будет Any more ideas? Это сообщение отредактировал(а) ldr12 - 10.2.2007, 02:47 |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
Вот, что у меня заработало!
но только одно "но". под отладкой виснет на PeekMessage. а когда отдельно запущено - то все ок. после Ctrl+Esc появляется лог с журналом)
-------------------- There are always someone smarter than you... |
|||
|
||||
| ldr12 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
Мля
Запустил как твой, так и свой код не через F9 - все прекрасно работает. Запустил снова через Delphi - виснет. Спасибо большое, я бы вряд ли в ближайшее время догадался искать ошибку там |
|||
|
||||
| MetalFan |
|
|||
![]() Аццкий Сотона ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3815 Регистрация: 2.10.2006 Где: Moscow Репутация: 16 Всего: 128 |
ldr12, да, видимо делфя что-то не поделила с отлаживаемым приложением... ))
-------------------- There are always someone smarter than you... |
|||
|
||||
| ldr12 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 9.2.2007 Репутация: 1 Всего: 1 |
Ну это ее проблемы, последнее слово за OS
|
|||
|
||||
![]()
|
| Правила форума "Delphi: WinAPI и системное программирование" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |