Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Хук срабатывает несколько раз. Почему?

Автор: sunduk4
Дата сообщения: 20.02.2005 12:55
Сделал глобальный хук на открытие/закрытие и потерю/получение фокуса -


Код:
Library HookDLL;

Uses
Windows, Messages, SysUtils, forms;

Const
GlobMapID = 'Global Hook {917C91AA-88D5-4134-BB91-15161728594D}';


Type
PShareInf = ^TShareInf;
TShareInf = Record
AppWndHandle: HWND;
OldHookHandle: HHOOK;
hm:THandle;
End;

Var
MapHandle: THandle = 0;
ShareInf: PShareInf = nil;
ptr:PByteArray;
f: TextFile;

Procedure DLLEntryPoint(dwReason: DWORD); stdcall;
Begin
Case dwReason Of
DLL_PROCESS_ATTACH:
Begin
MapHandle:=CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TShareInf), GlobMapID);
ShareInf:=MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TShareInf));
End;
DLL_PROCESS_DETACH:
Begin
UnMapViewOfFile(ShareInf);
CloseHandle(MapHandle);
End
End;
End;

function CallWndProc(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT;stdcall;
begin
if Code in [HC_ACTION, HC_NOREMOVE] then begin
if TCWPStruct(Pointer(ParamL)^).message = WM_CREATE then
writeln(f, 'Открыт файл ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_DESTROY then
writeln(f, 'Закрыт файл ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_SETFOCUS then
writeln(f, 'Получен фокус ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_KILLFOCUS then
writeln(f, 'Потерян фокус ' + application.exename);
end;
Result := CallNextHookEx(ShareInf^.OldHookHandle, Code, ParamW, ParamL)
end;

Function SetKeyboardHook(Wnd: HWND): BOOL; stdcall;
Begin
If ShareInf<>Nil Then
Begin
ShareInf^.AppWndHandle:=Wnd;
ShareInf^.OldHookHandle:=SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc, HInstance, 0);
Result:=ShareInf^.OldHookHandle<>0;
AssignFile(f, 'c:\bzreport.txt');
Append(f);
End
Else Result:=False
End;

Function RemoveKeyboardHook: BOOL; stdcall;
Begin
Result := UnhookWindowsHookEx(ShareInf^.OldHookHandle);
CloseFile(f);
CloseHandle(ShareInf^.hm);
End;

Exports
SetKeyboardHook, RemoveKeyboardHook;

BEGIN
If DLLProc = Nil Then DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
END.
Автор: OldGopher
Дата сообщения: 20.02.2005 23:49
Какие именно?
Это ведь system-wide hook.
Скажем, если одна аппликация нашла фокус, то другая потеряла. И это уже два вызова хука.

Или у Вас один и тот же massage ловится несколько раз для одной аппликации? Тогда надо смотреть параметры...
Автор: sunduk4
Дата сообщения: 21.02.2005 06:36
Одно и тоже сообщение ловится несколько раз. Например, при открытии блокнота, в логе получаю 6 записей "Открыт файл c:\windiws\notepad.exe".
Автор: ShIvADeSt
Дата сообщения: 21.02.2005 09:33
sunduk4
попробуй так

Цитата:
function CallWndProc(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT;stdcall;
begin
if Code in [HC_ACTION, HC_NOREMOVE] then begin
if TCWPStruct(Pointer(ParamL)^).message = WM_CREATE then
writeln(f, 'Открыт файл ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_DESTROY then
writeln(f, 'Закрыт файл ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_SETFOCUS then
writeln(f, 'Получен фокус ' + application.exename);
if TCWPStruct(Pointer(ParamL)^).message = WM_KILLFOCUS then
writeln(f, 'Потерян фокус ' + application.exename);
result:=0
end
else Result := CallNextHookEx(ShareInf^.OldHookHandle, Code, ParamW, ParamL)
end;

Автор: sunduk4
Дата сообщения: 21.02.2005 11:22
Попробовал. 98-я выдала синий экран, в XP вроде не настолько мертво повисла - explorer.exe отвалился.

Добавлено:
Прошу прощения у модераторов, но может есть еще у кого какие мысли?
Автор: OldGopher
Дата сообщения: 21.02.2005 21:34
sunduk4
При создании одной программы Notepad.exe создаются и открываются кучи окон. В Вашем случае - может быть шесть: фрейм, viewport и т.д...

По каждому окну идет глобальный хук. Каждое WM_CREATE обрабатывается отдельно, плюс кто-то получает фокус, кто-то теряет...

ShIvADeSt
Так нельзя делать.
Данный хук ставится перед посылкой сообщения окну. Следующая часть просто не получит уведомления о событии.

На эту тему много чего есть в MSDN.
Автор: ShIvADeSt
Дата сообщения: 22.02.2005 01:59
OldGopher

Цитата:
Данный хук ставится перед посылкой сообщения окну. Следующая часть просто не получит уведомления о событии.

Точно.

Цитата:
По каждому окну идет глобальный хук. Каждое WM_CREATE обрабатывается отдельно, плюс кто-то получает фокус, кто-то теряет...

Я примерно об этом же думал, если окно более менее сложное, то некотрые события вызываются несколько раз. А вообще человеку надо вот это

Цитата:

WH_CBT Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application. For more information, see the CBTProc hook procedure.

The CBTProc hook procedure is an application-defined or library-defined callback function that the system calls before activating, creating, destroying, minimizing, maximizing, moving, or sizing a window; before completing a system command; before removing a mouse or keyboard event from the system message queue; before setting the keyboard focus; or before synchronizing with the system message queue. The value returned by the hook procedure determines whether Windows allows or prevents one of these operations. A computer-based training (CBT) application uses this hook procedure to receive useful notifications from the system.

LRESULT CALLBACK CBTProc(

int nCode, // hook code
WPARAM wParam, // depends on hook code
LPARAM lParam // depends on hook code
);


Parameters

nCode

Specifies a code that the hook procedure uses to determine how to process the message. This parameter can be one of the following values:

Value Meaning
HCBT_ACTIVATE The system is about to activate a window.
HCBT_CLICKSKIPPED The system has removed a mouse message from the system message queue. Upon receiving this hook code, a CBT application must install a WH_JOURNALPLAYBACK hook procedure in response to the mouse message.
HCBT_CREATEWND A window is about to be created. The system calls the hook procedure before sending the WM_CREATE or WM_NCCREATE message to the window. If the hook procedure returns a nonzero value, the system destroys the window; the CreateWindow function returns NULL, but the WM_DESTROY message is not sent to the window. If the hook procedure returns zero, the window is created normally.
At the time of the HCBT_CREATEWND notification, the window has been created, but its final size and position may not have been determined and its parent window may not have been established. It is possible to send messages to the newly created window, although it has not yet received WM_NCCREATE or WM_CREATE messages. It is also possible to change the position in the Z order of the newly created window by modifying the hwndInsertAfter member of the CBT_CREATEWND structure.
HCBT_DESTROYWND A window is about to be destroyed.
HCBT_KEYSKIPPED The system has removed a keyboard message from the system message queue. Upon receiving this hook code, a CBT application must install a WH_JOURNALPLAYBACK_hook hook procedure in response to the keyboard message.
HCBT_MINMAX A window is about to be minimized or maximized.
HCBT_MOVESIZE A window is about to be moved or sized.
HCBT_QS The system has retrieved a WM_QUEUESYNC message from the system message queue.
HCBT_SETFOCUS A window is about to receive the keyboard focus.
HCBT_SYSCOMMAND A system command is about to be carried out. This allows a CBT application to prevent task switching by means of hot keys.

По крайней мере я видел, что именно таким образом отлавливали создание закрытие приложений.
Автор: sunduk4
Дата сообщения: 22.02.2005 10:41
Почитал справку по WH_CBT, вот что вышло:


Код:

function CBTProc(Code: Integer; ParamW: WPARAM; ParamL: LPARAM): LRESULT;stdcall;
begin

if code > 0 then begin

if code = HCBT_CREATEWND then
writeln(f, 'Открыт файл ' + application.exename);

if code = HCBT_DESTROYWND then
writeln(f, 'Закрыт файл ' + application.exename);

if code = HCBT_SETFOCUS then
writeln(f, 'Получен фокус ' + application.exename);

Result := 0;
exit;
end;
Result := CallNextHookEx(ShareInf^.OldHookHandle, Code, ParamW, ParamL);
end;


Автор: ShIvADeSt
Дата сообщения: 22.02.2005 10:54
sunduk4
Почитай здесь
http://www.xakep.ru/magazine/xa/046/072/1.asp
там как раз рассмтаривается отслеживание запуска закрытия приложений
Автор: OldGopher
Дата сообщения: 22.02.2005 20:59
Все хорошо - если приложение оконное. А если консольное - тогда только драйвер или хук базовой NTDLL Вам поможет. Последнее, опасно с точки зрения совместимости...


Добавлено:
ShIvADeSt
Какая-то статья... ракообразная, что ли...
Автор: sunduk4
Дата сообщения: 23.02.2005 18:43
Где можно статью хорошую по написанию драйвера прочитать? Мне вообще-то нужно, чтобы ловушка и в 98-й работала и в NT.
Автор: OldGopher
Дата сообщения: 24.02.2005 08:31
sunduk4
Отделите мухи от компота. Отдельно жрайверы - отдельно ловушки, кстати, вышеприведенная ловушка сработает во всех Windows, но только для оконных аппликаций.

Драйверы для XP - найдите книгу Walter Owney на осле. По WDM драйверам. Подходит для 2000+ и 98+...
Автор: sunduk4
Дата сообщения: 24.02.2005 14:47
Извиняюсь, некорректно изложил мысли. Я понимаю, что это разные вещи. Просто думаю, что вопрос с консольными приложениями все равно рано или поздно встанет. Буду копать в сторону драйверов. Спасибо всем ответившим.
Автор: OldGopher
Дата сообщения: 24.02.2005 18:36
sunduk4
Для Windows NT4+ есть пример драйвера в общей работе Ivo Ivanov по хукированию системных API на сайте www.codeproject.com

Там, правда, есть баги, и он не довел до конца работу с Windows 98+, но и так сойдет...
Автор: sunduk4
Дата сообщения: 26.02.2005 15:33
OldGopher
Спасибо за ссылку. Довольно интересная статья. Буду разбираться.

Страницы: 1

Предыдущая тема: Delphi-компонент для коннекта к NTP серверам


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.