Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Хук без формы


Автор: Dmitry_177 31.12.2006, 02:40
Если нужно сделать хук без формы, нужно всеравно создавать цикл сообщений т.е. примерно так?

Код

 hKeyHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, hInstance, 0);
 if hKeyHook = 0 then PostQuitMessage(GetLastError);

 while GetMessage(AMessage, 0, 0, 0) do
 begin
   TranslateMessage(AMessage);
   DispatchMessage(AMessage);
 end;

 UnhookWindowsHookEx(hKeyHook);


Или надо еще какнибудь?

Автор: bems 31.12.2006, 04:45
для *_LL  -хуков цикл обработки сообщение нужен.  TranslateMessage можно убрать.

if hKeyHook = 0 then PostQuitMessage(GetLastError) 
ну это слишком smile

Может даже не начинать цикл если не вышло, а?

Автор: bems 31.12.2006, 05:01
если возникнут проблемы с этим кодом попробуй перед SetWindowsHookEx заранее создать себе очередь сообщений (например "безобидным" вызовом PeekMessage)

Автор: Dmitry_177 31.12.2006, 11:29
Т.е. я как понял вот так?
Код

 hKeyHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, hInstance, 0);
 if hKeyHook = 0 then Exit;  // Если PostQuitMessage(GetLastError) слишком

 while GetMessage(AMessage, 0, 0, 0) do
   DispatchMessage(AMessage);

 UnhookWindowsHookEx(hKeyHook);

Автор: Dmitry_177 31.12.2006, 13:01
А еще такой вопрос, такую программу ИМХО можно отключить только в диспетчере задачь или какой-нибудь функцией завершения потока или сама она выключится по завершению работы Windows, а вопрос в том, то что будет ли в таком случае UnhookWindowsHookEx(hKeyHook); срабатывать после цикла сообщений? Мне кажется что нет... Если нет то как правильно снимать хук? Может в полях initialization создавать хук в а finalization убивать? Или еще как-то???

Автор: bems 31.12.2006, 15:00
хук принадлежит потоку и автоматически уничтожается при завершении потока (не процесса)

Добавлено @ 15:07 
Цитата(Dmitry_177 @  31.12.2006,  13:01 Найти цитируемый пост)
по завершению работы Windows
тогда в числе процих шлется WM_QUIT

Автор: Dmitry_177 4.1.2007, 01:57
1). WM-сообщения они же оконные, разве будут они слаться в данном случае, когда нету в приложении окна?

2). Если все же будут слаться, т.е. WM_QUIT как его обрабатывать? В цикле придется? Т.е. так?
Код

while GetMessage(AMessage, 0, 0, 0) do
  begin
    if AMessage.Message = WM_QUIT then
      begin
        UnhookWindowsHookEx(hKeyHook);
        // другие действия по завершению программы, сохранение данных например..
      end;
    DispatchMessage(AMessage);
  end;


Если не так поправьте меня пожалуйста..

Автор: bems 4.1.2007, 05:28
Цитата(Dmitry_177 @  4.1.2007,  01:57 Найти цитируемый пост)
будут они слаться в данном случае, когда нету в приложении окна?
кое-какие будут


Цитата(Dmitry_177 @  4.1.2007,  01:57 Найти цитируемый пост)
 WM_QUIT как его обрабатывать? 
когда GetMessage находит в очереди єто сообщение рна возвращает false. Цикл обработки сообщений прекращается 
Код

while GetMessage(AMessage, 0, 0, 0) do

Вот тут уже есть реакция на WM_QUIT

Автор: Dmitry_177 4.1.2007, 23:43
Т.е. так? 

Код

 while GetMessage(AMessage, 0, 0, 0) do
   DispatchMessage(AMessage);

 UnhookWindowsHookEx(hKeyHook);
 // Сохраняем данные

Автор: bems 5.1.2007, 01:39
ага

Автор: Dmitry_177 5.1.2007, 02:17
Сделал "сохранение данных" после такого цикла, в файле сохраняю, не сохраняются, по завершению программы(выключал из диспетчера задачь и windows выключал с работающей программой).. Ну не сохраняются они...(((

Автор: bems 7.1.2007, 06:33
Цитата(bems @  31.12.2006,  15:00 Найти цитируемый пост)
тогда в числе процих шлется WM_QUIT
не шлется, я соврал  smile  , сори
И не потому что нет окна, а потому что вместо него предполагается реакция приложения на WM_ENDSESSION, а оно шлется окнам  smile 
Если ты не хочешь создавать свое окно, то поставь еще один хук (WH_CALLWNDPROC) и лови это сообщение, когда идет другим окнам. 
Есть еще вариант написать WinLogon notification package, но это из пушки по воробьям

Добавлено @ 06:37 
А если пишешь кейлогер, то вообще лучше сохранять данные на лету, потому что от вырубания через таскманагер тебя ни что не спасет

Автор: Dmitry_177 9.1.2007, 02:35
Если ты не хочешь создавать свое окно, то поставь еще один хук (WH_CALLWNDPROC) и лови это сообщение, когда идет другим окнам.

Какое сообщение WM_QUIT или WM_ENDSESSION?

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

А вот как быть если мою такую программу хотят выключить через диспетчер задачь? Можно ли это какнибудь отлавливать?

Автор: bems 9.1.2007, 02:51
Цитата(Dmitry_177 @  9.1.2007,  02:35 Найти цитируемый пост)
Какое сообщение WM_QUIT или WM_ENDSESSION?
WM_ENDSESSION

Цитата(Dmitry_177 @  9.1.2007,  02:35 Найти цитируемый пост)
цикл тогда никогда не заканчивается по сути, если WM_QUIT не шлется?
ну в этом и была твоя проблема вроде бы. Ты ж сам писал: после цикла создаю файл, а файл не создается. Значит до "после цикла" дело не доходит

Цитата(Dmitry_177 @  9.1.2007,  02:35 Найти цитируемый пост)
А вот как быть если мою такую программу хотят выключить через диспетчер задачь? Можно ли это какнибудь отлавливать? 
Против лома нет приема. Можно прехватывать АПИ, но этого не делают всуе

Автор: Dmitry_177 9.1.2007, 05:22
У меня тогда еще несколько вопросов, надеюсь что последние:

1. Если цикл никогда не заканчивается и т.д., вот так нормально будет оставить или лучше как-то еще его написать?
Код

while GetMessage(AMessage, 0, 0, 0) do
   DispatchMessage(AMessage);


2. Правильно ли будет так обрабатывать хук на WM_ENDSESSION?
Код

function MessageProc(nCode: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
begin
  if nCode = HC_ACTION then
    Result := CallNextHookEx(hMsgHook, nCode, WParam, LParam);
  if WParam = WM_ENDSESSION then
    begin
      // сохраняем данные
    end;
end;

...

hMsgHook := SetWindowsHookEx(WH_CALLWNDPROC, @MessageProc, hInstance, 0);


3. Если делать перехват АПИ, на какую(ие) лучше функцию(ии) ставить перехват, которая(ые) может/могут вырубить мою программу?

Автор: bems 9.1.2007, 23:46
Цитата(Dmitry_177 @  9.1.2007,  05:22 Найти цитируемый пост)
1. Если цикл никогда не заканчивается и т.д., вот так нормально будет оставить или лучше как-то еще его написать?
нормально

Цитата(Dmitry_177 @  9.1.2007,  05:22 Найти цитируемый пост)
Правильно ли будет так обрабатывать хук на WM_ENDSESSION?
вобщем да, но что случиться если тачку перезагрузят некорректно?

Цитата(Dmitry_177 @  9.1.2007,  05:22 Найти цитируемый пост)
3. Если делать перехват АПИ, на какую(ие) лучше функцию(ии) ставить перехват, которая(ые) может/могут вырубить мою программу? 
ищи по форуму

Автор: Dmitry_177 10.1.2007, 01:50
Запустил свою программу с кодом из пункта 2, функцию MessageProc обработки хука написал как тут, скопировал точнее, запустил, у меня аж Delphi вырубилась как только скомпилировалась программа и токо-токо успела запуститься.. Просто изначально писал код без delphi, т.к. небыло тогда его рядом... И что-то я не пойму никак почему так...??? Вроде все правильно...

Автор: bems 10.1.2007, 08:44
Код

begin
  // сохраняем данные
end;

А тут все нормально?

хук WH_CALLWNDPROC работает в контексте чужого процесса. Поэтому сохранение данных должно быть продуманым и синхронизированым. Учитывая доступность памяти и хэндлов

Добавлено @ 08:59 
hMsgHook известен в библиотеке?
если нет, то лучше вместо него в вызове CallNextHookEx передавай ноль. Начиная с 2000й это работает.

В этой процедуре хука wparam это не сообщение. Сообщение лежит в структуре  CWPSTRUCT указатель на которую передается в lparam

nCode = HC_ACTION означает что тут может быть твоя обработка, а CallNextHookEx нужно вызывать во всех случаях

Автор: Dmitry_177 10.1.2007, 10:47
WH_CALLWNDPROC нужно в dll ставить??  smile 
Я в программе сделал... мне надо в программе, чтобы безо всяких там dll-ок...

Автор: bems 11.1.2007, 01:04
без длл не выйдет

Автор: Dmitry_177 11.1.2007, 16:54
Т.е. отследить выключение windows без длл в моем случае никак нельзя, кроме как перехвата api функций?

Автор: bems 14.1.2007, 01:00
ну можно создат окно нулевых размеров, но тебе это вроде не подходило... Или может быть?

Автор: Dmitry_177 14.1.2007, 01:18
нет.. окно создавать не подходит...

Автор: bems 16.1.2007, 01:16
Цитата(Dmitry_177 @  14.1.2007,  01:18 Найти цитируемый пост)
нет.. окно создавать не подходит... 
тогда лучше ДЛЛ? опиши задачу, имхо окно меньший оверхед... Или дело в шифрованости? тогда всеравно не то...

Автор: Dmitry_177 16.1.2007, 01:43
Что значит оверхед? )))

Или дело в шифрованости?
Типа того.. Есть программы - анализаторы кода, которые секут невидимые окна.. Поэтому хочу обойтись без окон.. dll- тоже быстро секутся некоторыми программами, ведь при хуке происходит инжект dll в чужие программы... А вот хук на WH_KEYBOARD_LL к моему удивлению не секется, покрайней мере теми которыми я проверял... Скорей всего это из-за того что программа работает напрямую с драйвером клавиатуры...

Вот понадобилось запуск и остановку компьютера отслеживать.. С запуском все понятно, при запуске проги будет производиться запись что комп включен, т.к. она будет запускаться при запуске.. А вот с выключением уже проблемы...((( До сих пор все парюсь, никак ничего не придумаю...(((

Автор: bems 16.1.2007, 18:22
ну пиши куда-нить 
17:32:12 - все спокойно
17:32:13 - все спокойно
17:32:14 - все спокойно

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

Автор: Dmitry_177 16.1.2007, 20:46
Ок, идею понял )))


M
Girder
Одна тема - один вопрос!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)