Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Power Basic

Страница: 1 | 2 | 3 |

 

  Вопрос: Нужна помощь с хуком Добавлено: 25.11.08 15:46  

Автор вопроса:  Lapex
Всем привет!

Пожалуйста помогите разобраться...

Пишу к приложению плагин (dll), мне необходимо узнать handle окна которое создается приложением и перехватить сообщение закрытия этого окна.

У окна известен заголовок "Project" (я не уверен, что разработчики приложения в дальнейшем его не изменят) и имя класса "Afx:400000:3:0:6:......" у которого при каждом запуске окна меняются последние 6 символов.

Предполагаю нужно сделать следующее:
В CASE %DLL_PROCESS_ATTACH содать таймер (не уверен, можно ли здесь запускать таймер), в которм ожидать появление окна с именем класса содержащего подстроку "Afx:400000:3:0:6:". Получить handle этого окна, запустить hook для отслеживания сообщений окна и остановить таймер.

Поправьте меня, если мое предположение ошибочно, а также у меня большая просьба, если не трудно помочь примером установки хука на сообщения указанного окна. Буду очень благодарен.

Ответить

  Ответы Всего ответов: 42  

Номер ответа: 1
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #1 Добавлено: 25.11.08 18:25
Зачем же таймер, при инициализации длл ставим хук WH_CBT, отлавливаем HCBT_CREATWND, проверяем LPARAM являющийся хендлом создаваемого окна на соответствие класса и заголовка и потом уже над ним издеваемся.

Ответить

Номер ответа: 2
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #2 Добавлено: 25.11.08 21:48
Вообщем отлавить окно с помощью HCBT_CREATWND не удалось, пока поймал его с помощью HCBT_ACTIVATE. Ниже набросал код, который отлавливает сообщение окна WM_CLOSE, но программа с этим кодом глючит. При сворачивании окна приложение - приложение закрывается :(.
Пожалуйста подскажите, что не так с кодом.
  1.  
  2. #COMPILE DLL
  3. #INCLUDE  "Win32API.inc"
  4.  
  5. GLOBAL hHook      AS LONG
  6. GLOBAL hWnd       AS DWORD
  7. GLOBAL pWndProc   AS LONG
  8. GLOBAL ghInstance AS DWORD
  9.  
  10. FUNCTION LIBMAIN (BYVAL hInstance   AS LONG, _
  11.                   BYVAL fwdReason   AS LONG, _
  12.                   BYVAL lpvReserved AS LONG) AS LONG
  13.  
  14.   SELECT CASE fwdReason
  15.     CASE %DLL_PROCESS_ATTACH
  16.       ghInstance = hInstance
  17.       CALL SetHook()
  18.       FUNCTION = 1
  19.     CASE %DLL_PROCESS_DETACH
  20.       UnhookWindowsHookEx hHook
  21.       FUNCTION = 1
  22.     CASE %DLL_THREAD_ATTACH
  23.       FUNCTION = 1
  24.     CASE %DLL_THREAD_DETACH
  25.       FUNCTION = 1
  26.   END SELECT
  27. END FUNCTION    
  28.  
  29. FUNCTION SetHook ALIAS "SetHook" () EXPORT AS LONG
  30.     hHook = SetWindowsHookEx (%WH_CBT, CODEPTR(HookProc), BYVAL ghInstance, BYVAL GetCurrentThreadId)
  31. END FUNCTION
  32.  
  33. CALLBACK FUNCTION WndProc
  34.     SELECT CASE CBMSG
  35.         CASE %WM_CLOSE
  36.             MSGBOX "Exit"
  37.     END SELECT
  38.     FUNCTION = CallWindowProc(pWndProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM)
  39. END FUNCTION
  40.  
  41. FUNCTION HookProc (  BYVAL nCode AS LONG, _
  42.                      BYVAL wParam AS LONG, _
  43.                      BYVAL lParam AS LONG) EXPORT AS LONG
  44.  
  45.     LOCAL ClassName AS ASCIIZ * %MAX_PATH
  46.     IF nCode = %HCBT_ACTIVATE THEN
  47.         GetClassName wParam, ClassName, SIZEOF(ClassName): _
  48.         IF LEFT$(ClassName,17) = "Afx:400000:3:0:6:" THEN hWnd = wParam
  49.         IF hWnd <> 0 THEN
  50.             pWndProc = SetWindowLong (hWnd, %GWL_WNDPROC, CODEPTR(WndProc))
  51.         END IF
  52.     END IF
  53. END FUNCTION

Ответить

Номер ответа: 3
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #3 Добавлено: 26.11.08 04:13
   Поправка, при HCBT_CREATWND в WPARAM передается хендл окна, а в LPARAM передается адрес структуры CBT_CREATEWND, первое поле которой является адресом структуры CREATESTRUCT, в ней есть поле lpszClass - указатель на строку класса окна, так что GetClassName не нужна.
   Глючит видимо потому, что HCBT_ACTIVATE происходит неоднократно, и уже при втором вызове SetWindowLong(... оконная процедура начинает вызывать саму себя, со всеми вытекающими отсюда засадами.

Ответить

Номер ответа: 4
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #4 Добавлено: 26.11.08 10:28
в LPARAM передается адрес структуры CBT_CREATEWND, первое поле которой является адресом структуры CREATESTRUCT, в ней есть поле lpszClass - указатель на строку класса окна


Спасибо за совет, но у меня ничего не вышло - выдает ошибку (Period not allowed) в строке с CREATESTRUCT.lpszClass.

  1.  
  2. FUNCTION HookProc (  BYVAL nCode AS LONG, _
  3.                      BYVAL wParam AS LONG, _
  4.                      BYVAL lParam AS LONG) EXPORT AS LONG
  5.  
  6.   LOCAL ClassName AS ASCIIZ * %MAX_PATH
  7.   IF nCode = %HCBT_CREATEWND THEN
  8.     CREATESTRUCT = CODEPTR(lParam)
  9.     IF LEFT$(CREATESTRUCT.lpszClass,17) = "Afx:400000:3:0:6:" THEN hWnd = wParam
  10.         IF hWnd <> 0 THEN
  11.             pWndProc = SetWindowLong (hWnd, %GWL_WNDPROC, CODEPTR(WndProc))
  12.         END IF
  13.     END IF
  14. END FUNCTION


Пожалуйста, если не трудно - покажи, как добыть имя класса из LPARAM.

Ответить

Номер ответа: 5
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #5 Добавлено: 26.11.08 11:32
Sorry, предыдущий код - полный бред.
Вот, что у меня получилось - но все равно не работает :(
  1.  
  2. FUNCTION HookProc (  BYVAL nCode AS LONG, _
  3.                      BYVAL wParam AS LONG, _
  4.                      BYVAL lParam AS LONG) EXPORT AS LONG
  5.  
  6.     LOCAL cw AS CBT_CREATEWND PTR, cst AS CREATESTRUCT PTR
  7.     LOCAL pClassName AS ASCIIZ PTR
  8.  
  9.     IF nCode = %HCBT_CREATEWND THEN
  10.         cw = lParam    
  11.         cst = @cw.lpcs  
  12.         pClassName = @cst.lpszClass
  13.         IF LEFT$(@pClassName,17) = "Afx:400000:3:0:6:" THEN hWnd = wParam
  14.  
  15.         IF hWnd <> 0 THEN
  16.             pWndProc = SetWindowLong (hWnd, %GWL_WNDPROC, CODEPTR(WndProc))
  17.         END IF
  18.     END IF
  19. END FUNCTION

Ответить

Номер ответа: 6
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #6 Добавлено: 27.11.08 11:30
  1.  
  2. HHOOK hhook;
  3. HWND hWnd;
  4.  
  5. LRESULT CALLBACK CBTProc( int nCode, WPARAM wParam,  LPARAM lParam )
  6. {
  7. if (nCode < 0) return CallNextHookEx(hhook, nCode, wParam, lParam);
  8. switch (nCode)
  9. {
  10. case HCBT_CREATEWND:
  11. if (hWnd) break; // НЕ ЗАБЫВАЙ !!
  12. hWnd = (HWND) wParam;
  13. CBT_CREATEWND* cw;
  14. CREATESTRUCT* cst;
  15. cw = (CBT_CREATEWND*) lParam;
  16. cst = (CREATESTRUCT*) cw->lpcs;
  17. MessageBox(0, cst->lpszName, 0, 0);
  18. //SetWindowLong(...
  19. break;
  20. default:
  21. break;
  22. }
  23. return CallNextHookEx(hhook, nCode, wParam, lParam);
  24. }
  25. //...


Вот у тебя есть такое:
        IF hWnd <> 0 THEN
            pWndProc = SetWindowLong (hWnd, %GWL_WNDPROC, CODEPTR(WndProc))
        END IF
Это что же, опять повторный вызов? Не хорошо... :)

Ответить

Номер ответа: 7
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #7 Добавлено: 27.11.08 12:39
Это что же, опять повторный вызов? Не хорошо...

Мда, ступил :)

К сожалению Си я не знаю, но думаю, что выглядеть должно так:
  1.  
  2. FUNCTION HookProc (  BYVAL nCode AS LONG, _
  3.                      BYVAL wParam AS LONG, _
  4.                      BYVAL lParam AS LONG) EXPORT AS LONG
  5.  
  6.     LOCAL cw AS CBT_CREATEWND PTR, cst AS CREATESTRUCT PTR
  7.     LOCAL pClassName AS ASCIIZ PTR
  8.  
  9.     IF nCode = %HCBT_CREATEWND THEN
  10.         IF hWnd = 0 THEN
  11.             cw = lParam
  12.             cst = @cw.lpcs
  13.             pClassName = @cst.lpszClass
  14.  
  15.             IF LEFT$(@pClassName,17) = "Afx:400000:3:0:6:" THEN
  16.                 hWnd = wParam
  17.                 pWndProc = SetWindowLong (hWnd, %GWL_WNDPROC, CODEPTR(WndProc))
  18.             END IF
  19.         END IF
  20.     END IF
  21.     FUNCTION = CallNextHookEx(hHook, nCode, wParam, lParam)
  22. END FUNCTION


Ситуация не изменилась :(.

Ответить

Номер ответа: 8
Автор ответа:
 Father



Вопросов: 0
Ответов: 159
 Профиль | | #8 Добавлено: 27.11.08 18:48
Я не учел, что basic по своему работает с указателями,
попробуй так.
  1.  
  2.    LOCAL cw AS CBT_CREATEWND PTR
  3.    LOCAL cst AS CREATESTRUCT PTR
  4.    LOCAL ClassName AS ASCIIZ * %MAX_PATH
  5.    cw = lParam
  6.    cst = @cw.lpcs
  7.    CopyMemory  VARPTR(ClassName), @cst.lpszName, %MAX_PATH
  8.    'LOCAL MyString AS STRING
  9.    'MyString = LEFT$(ClassName, ...

Ответить

Номер ответа: 9
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #9 Добавлено: 27.11.08 20:21
Ошибка: Память не может быть "read".

Ответить

Номер ответа: 10
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #10 Добавлено: 28.11.08 13:03
Ситуация немного изменилась - удалось получить handle окна приложения, с помощью FindWindow в одной из ф-ций плагина (dll), которые опрашиваются при запуске приложения.
Дальше буду разбираться с перехватом сообщений этого окна.

Все таки хотелось-бы уточнить правильность указания последних двух параметров в SetWindowsHookEx:

hHook = SetWindowsHookEx (%WH_CBT, CODEPTR(HookProc), BYVAL ghInstance, BYVAL GetCurrentThreadId)

В инете не нашел примера установки хука из dll - везде установка происходит из exe, вот меня и берут сомнения по поводу последних двух параметров: ghInstance и GetCurrentThreadId.

Подскажите пожалуйста, корректна-ли выше указанная строка установки хука.

Ответить

Номер ответа: 11
Автор ответа:
 Ra$cal



ICQ: 8068014 

Вопросов: 18
Ответов: 817
 Web-сайт: www.rascalspb.narod.ru
 Профиль | | #11
Добавлено: 28.11.08 13:33
  1. void SetCBTHook()
  2. {
  3.  
  4. cbt_hook = SetWindowsHookEx(WH_CBT, CBTProc, GetModuleHandle(dll_name), 0);
  5. if (cbt_hook == 0){
  6. Beep (500, 100);
  7. }
  8. }

Ответить

Номер ответа: 12
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #12 Добавлено: 28.11.08 18:02
Я хотел узнать, какой hInstance нужен в моем случае: приложения (exe) или dll?

Ответить

Номер ответа: 13
Автор ответа:
 Ra$cal



ICQ: 8068014 

Вопросов: 18
Ответов: 817
 Web-сайт: www.rascalspb.narod.ru
 Профиль | | #13
Добавлено: 29.11.08 08:18
GetModuleHandle(dll_name) - на чей инстанс похоже? =)

Ответить

Номер ответа: 14
Автор ответа:
 Lapex



Вопросов: 6
Ответов: 56
 Профиль | | #14 Добавлено: 29.11.08 09:25
Ну, это понятно - в своем коде я тоже использую hInstance для dll,вопрос возник из-за того, что у меня возникают ошибки с другими окнами, которые не попадают в фильтр хука. Вот и взяди меня сомнения по поводу hInstance, но скорее всего дело в валидности моего хука.

Спасибо всем за оказанную помощь, буду разбираться.

Ответить

Номер ответа: 15
Автор ответа:
 Ra$cal



ICQ: 8068014 

Вопросов: 18
Ответов: 817
 Web-сайт: www.rascalspb.narod.ru
 Профиль | | #15
Добавлено: 29.11.08 13:19
есть тока одно объяснение такому косяку - хэндл хука лежит не в шэйред мемори, в итоге в чужих процессах хэндл хука != реальному хэндлу.

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам