Форум программистов, компьютерный форум, киберфорум
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/15: Рейтинг темы: голосов - 15, средняя оценка - 4.67
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25

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

20.03.2016, 10:18. Показов 3038. Ответов 37

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Имеется задача: перехватывать нажатие клавиш во всей системе. После изучения статей про хуки написал что-то очень близкое к правде.
Имею звуковой сигнал (простой пи-пип) на любую клавишу в любом приложении, кроме приложений системных. А именно: стоит нажать какую-либо кнопочку в блокноте, паинте, IE, проводнике, на голом рабочем столе и в им подобных приложениях - приложение (которое было в фокусе) зависает намертво.

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

Установка ловушки в программе (на FreePascal):
Pascal
1
2
3
4
descDLL:=LoadLibrary('dll.dll');
descFunc:=HOOKPROC(GetProcAddress(descDLL,'KeyBoardHook'));
descHook:=SetWindowsHookEx(2, descFunc, descDLL, 0);
Writeln(stngs,IntToStr(descHook)); //Пишем дескриптор в файл
Функция-фильтр ловушки в dll:
Pascal
1
2
3
4
5
6
7
8
9
10
function KeyBoardHook(code:integer; wparam:wparam; lparam:lparam):Lresult; stdcall;
begin
if (CurHook=0) then Start; //Читает из файла дескриптор ловушки и пишет его в CurHook
windows.beep(200,70);
 if code<0 then begin  and
       KeyBoardHook:=CallNextHookEx(CurHook,code,wParam,lparam); 
       Exit;
 end;
 CallNextHookEx(CurHook,code,wParam,lparam);
 KeyBoardHook:=0;
Остальной код приводить не вижу смысла, тут вроде все должно быть ясно.
Дескриптор ловушки, как видно из комментов, записываю в файл сразу после установки.

С остальными (сторонними) приложениями всё работает как надо. Любые браузеры, редакторы и т.п. - всё послушно пикает.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.03.2016, 10:18
Ответы с готовыми решениями:

Глобальный хук клавиатуры
Привет. Мне нужно сделать глобальный хук клавиатуры, но я не знаю как. В интернете примеров на C++ мало и все не работают, потому что люди...

Глобальный хук клавиатуры
Я пишу программу с функцией воспроизведения. Мне нужно, что бы программа при нажатии на клавишу начинала воспроизведение, или...

Глобальный хук клавиатуры (windows)
Как программно можно остледить нажатие клавиши, если активно другое окно? Поиском нашёл GetAsyncKeyState, но она не подходит, т.к. данный...

37
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 13:02
Delphi
1
2
3
4
5
function KeyBoardHook(code:integer; wparam:wparam; lparam:lparam):Lresult; stdcall;
begin
  windows.beep(200,70);
  Result := CallNextHookEx(0,code,wParam,lparam); 
end;
А все эти непонятно зачем понадобившиеся бубнопляски с записью/чтением дескриптора хука в файл убери.
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 14:18  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
А все эти непонятно зачем понадобившиеся бубнопляски с записью/чтением дескриптора хука в файл убери.
Бубнопляски с декспритором описаны в подавляющем большинстве статей про хуки.
В самых последних указывается, что можно отдавать просто нуль и ОС сама сообразит какой фильтр следующий. Но их я прочитал уже позже.

К тому же, это дела не меняет.
С такой ловушкой проблема всё та же..

Исходя из полного отсутствия "бипа", могу предположить, что все эти блокноты и еже с ними вообще не доходят до ловушки, а по какой-то причине зависают до неё...
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 15:20
Цитата Сообщение от D_Fox Посмотреть сообщение
это дела не меняет
Ты не рассуждай, а просто удали всю эту хренотень из тела ф-ции)
Оставь одну строчку
Result := CallNextHookEx(0,code,wParam,lparam);

Вот когда "зависания" исчезнут - тогда и рассуждать будешь)
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 15:41  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Ты не рассуждай, а просто удали всю эту хренотень из тела ф-ции)
А Вы читайте, пожалуйста, внимательней
Я же написал, что с такой (как в Вашем первом ответе) ловушкой - проблемы те же.
И даже если би-бип убрать, оставив только Result:=CallNextHookEx<..> - всё одно.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 15:46
Ну не знаю..
С единственной строчкой

Result := CallNextHookEx(0,code,wParam,lparam);

у меня ни один процесс не зависает

Что я не так делаю ?)
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 15:53  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Что я не так делаю ?)
Т.е., вы устанавливаете ловушку с таким же, для примера, звуковым сигналом.

И этот самый сигнал звучит при клацанье клавы везде, в т.ч. и в блокноте и на "голом" рабочем столе?

Код установки ловушки аналогичен моему? (за вычетом записи в файл, конечно).

Добавлено через 2 минуты
Если всё вышеспрошенное - так.
Позвольте узнать три вещи:

1. Ваша ОС.
2. Компилятор (но что-то я сомневаюсь, что в нем собака зарыта).
3. Весь код проги и dll, дабы я мог в точности воспроизвести. : )
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 15:55
Цитата Сообщение от D_Fox Посмотреть сообщение
Т.е., вы устанавливаете ловушку с таким же, для примера, звуковым сигналом
С одной-единственной строчкой:

Result := CallNextHookEx(0,code,wParam,lparam);

Никаких "сигналов" и прочей непотребщины - все по стандартному шаблону)

Цитата Сообщение от D_Fox Посмотреть сообщение
Код установки ловушки аналогичен моему?
По сути - да.

Добавлено через 1 минуту
1. XP SP3
2. Сиеттл
3. Не подаю из принципа)
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 15:59  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
1. XP SP3
2. Сиеттл
3. Не подаю из принципа)
Завтра попробую и на ХРюше.
Жаль, что принципы у Вас такие неудобные.

Цитата Сообщение от mss Посмотреть сообщение
Никаких "сигналов" и прочей непотребщины - все по стандартному шаблону)
А смысл просто передавать очередь? Ведь в "непотребщине" и суть.
Сигнал был лишь как тест, что ловушка сработала.

Вопрос всё ещё открыт.

Добавлено через 50 секунд
У меня FPC 2.6.4. И Win8.1. На 7-ке тестил, результат такой же (т.е. проблема есть).
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 16:08
Цитата Сообщение от D_Fox Посмотреть сообщение
Сигнал был лишь как тест, что ловушка сработала
Можно подумать что нет нормального способа отладки, которым и должен в первую очередь пользоваться программист - встроенный отладчик.

Добавлено через 2 минуты
Цитата Сообщение от D_Fox Посмотреть сообщение
У меня FPC 2.6.4
Мало ли какие либы он за собой в либу ловушки подтягивает)
Может в этом и проблема ?
0
Хитрая блондиночка $)
 Аватар для Hikari
1472 / 988 / 399
Регистрация: 21.12.2015
Сообщений: 3,785
20.03.2016, 16:21
Цитата Сообщение от D_Fox Посмотреть сообщение
зависает намертво.
Пробовал через CTRL+ALT+DEL достучаться до диспетчера задач при таких зависаниях?
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 16:43  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Можно подумать что нет нормального способа отладки, которым и должен в первую очередь пользоваться программист - встроенный отладчик.
Можно подумать, что из-за бипа всё и зависает; )

Цитата Сообщение от mss Посмотреть сообщение
Мало ли какие либы он за собой в либу ловушки подтягивает)
Может в этом и проблема ?
Может.

Цитата Сообщение от Hikari Посмотреть сообщение
Пробовал через CTRL+ALT+DEL достучаться до диспетчера задач при таких зависаниях?
Пробовал. Всё обычно: Состояние "Не отвечает", потребление ресурсов по нулям, только Память остается такой, какой и была до зависания.
Если приложение (допустим, блокнот) не успело убиться, то после аварийного завершения приложения с ловушкой - события, которые произошли во время зависания срабатывают (т.е. все клавиши "нажимаются". В блокноте - печатаются и т.д.).

Вот тут скопмпилированные файлы вместе с исходниками (некоторые антивирусы, само собой ругаются, типа кейлогер).
Яндекс.Диск.

Исходники целиком:
Кликните здесь для просмотра всего текста

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
program testing;
{$mode objfpc}{$H+}
 
uses Windows, sysutils;
 
var
descHook:HHOOK;
descDLL : HINST; 
descFunc: HOOKPROC;
 
begin
 
descDLL:=LoadLibrary('dll.dll');
descFunc:=HOOKPROC(GetProcAddress(descDLL,'KeyBoardHook'));
descHook:=SetWindowsHookEx(2, descFunc, descDLL, 0);
Sleep(60000);
UnhookWindowsHookEx(descHook);
 
end.
dll
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
library hook;
 
{$mode objfpc}{$H+}
 
 
uses
  Windows;
 
function KeyBoardHook(code:integer; wparam:wparam; lparam:lparam):Lresult; stdcall;
begin
  windows.beep(200,70);
  Result := CallNextHookEx(0,code,wParam,lparam); 
end;
 
exports KeyBoardHook;
 
begin
end.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 16:54
Цитата Сообщение от D_Fox Посмотреть сообщение
Можно подумать, что из-за бипа всё и зависает
А ты знаешь как бип работает ?)
С чего ты взял что это настолько тривиальная операция, что она не может "подвесить" ничего в принципе ?)

Цитата Сообщение от D_Fox Посмотреть сообщение
Может
Вот и выясняй)
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 17:00  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
А ты знаешь как бип работает ?)
С чего ты взял что это настолько тривиальная операция, что она не может "подвесить" ничего в принципе ?)
С того, что Вы вновь невнимательно читаете.

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

Цитата Сообщение от mss Посмотреть сообщение
Вот и выясняй)
Помощи от Вас масса ; )
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 17:10
Цитата Сообщение от D_Fox Посмотреть сообщение
Итог тот же
Ну а в следующий раз итог будет другим - будет висеть именно на бипе)
И что, опять будет ступор ?)
Учись и привыкай пользоваться правильным отладочным инструментарием, а не первым попввшимся методом имени Кулибина)

Цитата Сообщение от D_Fox Посмотреть сообщение
Помощи от Вас масса
Ловить нужно момент инициализации либы, а не момент срабатывания ф-ции.
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 17:18  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Ну а в следующий раз итог будет другим - будет висеть именно на бипе)
И что, опять будет ступор ?)
А в след.раз я снова проверю, бип-ли причина и всё Не на том Вы внимание концентрируете. Уж сколько сообщений назад было сказано, что с ОДНОЙ строчкой КэлНекст тоже не работает.
И что за "правильный" отладочный инструмент по-вашему? Примеру в студию. Хоть знать буду.

Цитата Сообщение от mss Посмотреть сообщение
Ловить нужно момент инициализации либы, а не момент срабатывания ф-ции.
В begin <...> end dll вписать что-то из вышеупомянутых отладочных плюшек? Или?
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
20.03.2016, 17:29
Цитата Сообщение от D_Fox Посмотреть сообщение
что за "правильный" отладочный инструмент по-вашему?
"правильный" инструмент - это отладчик, встроенный в интегрированную среду разработки.
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 17:53  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
"правильный" инструмент - это отладчик, встроенный в интегрированную среду разработки.
Это не хардкорно))

Для данной задачи вообще использую Geany. Отладка: обычные writeln(ну тут не проканывает) либо вывод в файл. Хватает.
А ну да, еще бики=РРР

Вопрос всё еще открыт.
Исходники и exe шник с dll я привёл выше.
Буду очень благодарен, если кто-нибудь проверит запустить и\или скомпилировать под чем-нибудь другим.
0
Хитрая блондиночка $)
 Аватар для Hikari
1472 / 988 / 399
Регистрация: 21.12.2015
Сообщений: 3,785
20.03.2016, 18:18
Цитата Сообщение от D_Fox Посмотреть сообщение
Вот тут скопмпилированные файлы вместе с исходниками (некоторые антивирусы, само собой ругаются, типа кейлогер).
Архив битый. Лучше просто pas прикрепи без скомпилированного.
Я могу проверить ибо работаю с Лазарусом.
В ответ могу приложить свои (из старенького) игрушки с хуком:

Хуковая библиотека:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
library hdll;
 
{$mode objfpc}{$H+}
 
uses
  Classes,windows, unitCallback
  { you can add units after this };
 
var h:HHOOK; f:textfile; cb:TCallback;
 
  function hEvent(nCode:longInt;wPara,lPara:integer):LRESULT; stdcall;
  var d:PCWPRETSTRUCT;
  begin
    if (nCode>=0)and(wPara<>0) then begin
      if Assigned(cb) then cb(nCode,wPara,lPara);
    end;
   Result:=CallNextHookEx(h,nCode,wPara,lPara);
  end;
 
function Hook(acb:TCallback;hctype:LongInt):Cardinal;   export;
var hp:HOOKPROC;
begin
   cb:=acb;
  Result:=h;
end;
 
function Unhook:Boolean; export;
begin
 Result:=UnhookWindowsHookEx(h);
end;
 
exports Hook,Unhook;
begin
end.
Приложение:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses    windows,  unitCallback,  msgs,
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
                Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
 
    { public declarations }
  end;
 procedure callbackMe(nCode:longInt;wPara,lPara:integer);
 Function Hook(acb:TCallback;act:LongInt):Cardinal; external 'hdll.dll';
 function Unhook:Boolean; external 'hdll.dll';
 
var     st:TstringList;
  Form1: TForm1;
 
implementation
 
procedure callbackMe(nCode: longInt; wPara, lPara: integer);
var d:PCWPRETSTRUCT; c,t:array[1..100] of char;
begin
 d:=Pointer(lPara);
 FillChar(c,100,0);FillChar(t,100,0);
 GetClassName(d^.hwnd,@c[1],100);
 GetWindowText(d^.hwnd,@t[1],100);
 st.Append(format('hwnd=%20d  msg='+MessageToStr(d^.message)+'(%20x) lParam=%20d wParam=%20d ('+Trim(c)+') - ['+trim(t)+']'
  ,[d^.hwnd,d^.message,d^.lParam,d^.wParam]));
end;
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  st.SaveToFile(ExtractFilePath(ParamStr(0))+'hook.txt');
  if Unhook then ShowMessage('Отцепились');
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var h:Cardinal;
begin
  st:=TStringList.Create;
  h:=hook(@callbackMe,WH_CALLWNDPROC);
  if h=0 then RaiseLastOSError else Caption:=IntToStr(h);
end;
 
end.
Проблем с зависанием именно с этим примером не замечала.
FPC 264 и 300. WinXP и Win7.
0
 Аватар для D_Fox
0 / 0 / 0
Регистрация: 27.10.2013
Сообщений: 25
20.03.2016, 18:43  [ТС]
Цитата Сообщение от Hikari Посмотреть сообщение
Архив битый. Лучше просто pas прикрепи без скомпилированного.
Хм..а у меня распаковался нормально..

Ну ладно. Вне архива вот.
Кстати, тоже есть Лазарус. Попробовал скомпилировать им: итог тот же. Хотя, возможно, там как-то иначе нужно было открыть файлы исходников..

Ваш пример завтра попробую. Спасибо=)
По результатам тестов моих исходников буду ждать вестей)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.03.2016, 18:43
Помогаю со студенческими работами здесь

KeyLogger (глобальный хук клавиатуры)
Не могу найти информацию по созданию кейлогера. Кто может помочь исходником или материалом?

Глобальный хук клавиатуры/мыши в Lazarus
Здравствуйте, не подскажете, что лучше использовать для глобального хука клавиатуры/мыши? Мне нужно, чтобы обрабатывался ввод...

KeyboardProc, глобальный хук клавиатуры, dll
Написал dll для установки хука на клаву, по книге &quot;Нестандартные приемы программирования на Delphi (Ю. Ревич)&quot; Программа должна...

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

Глобальный хук клавиатуры с целью изменить клавишу
Здравствуйте! Возможно ли с помощью глобального хука клавиатуры (SetWindowsHookEx, WH_KEYBOARD_LL) изменить получаемую им клавишу (при...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru