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

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

20.03.2016, 10:18. Показов 3121. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определённом условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru