• ЗапомниСынок (31.05.08 11:43) [0]
    Пытаюсь отловить сообщения окон при помощи SetWinEventHook
    Хук ставится, сообщения ловятся, все работает, но нередко
    после успешного вызова UnhookWinEvent, dll-файл не удается удалить (Delphi пишет: [Fatal Error] Could not create output file 'WinHook.dll'). Другими словами, библиотека не выгружается из адресного пространства каких-то процессов. С чем это может быть связано.

    const
      WM_EVENT_HOOK        = WM_USER + $FF;

    var
      hWinHook             : HWND;
      hLogWin              : HWND;

    function CheckWindow(hWnd : HWND) : Boolean;
    var
      WindowName : array[0..64] of Char;
      WindowClass : array[0..32] of Char;
    begin
    ...
    end;

    procedure HookProc(hWinEventHook: THandle; Event: DWORD; hWnd: HWND; idObject, idChild: Longint; idEventThread, dwmsEventTime: DWORD); stdcall;
    begin
    if (idObject = OBJID_WINDOW) and (idChild = CHILDID_SELF) then
      if CheckWindow(hWnd) then
         PostMessage(hLogWin, WM_EVENT_HOOK, hWnd, Event);
    end;

    function SetHook(State : Boolean; Manager : HWND) : Boolean; export; stdcall;
    begin
    if State then
      begin
      hWinHook := SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, hInstance, @HookProc, 0, 0, WINEVENT_INCONTEXT);
      Result := hWinHook > 0;
      end
    else
      begin
      Result := UnhookWinEvent(hWinHook);
      end;
    end;

    procedure DLLEntryPoint(dwReason:DWord);
    begin
    case dwReason of
      DLL_PROCESS_ATTACH:
         hLogWin := FindWindow(...)
      end;
    end;

    exports SetrHook;

    {$R *.res}

    begin
      DllProc:= @DLLEntryPoint;
      DLLEntryPoint(DLL_PROCESS_ATTACH);
    end.
  • Eraser © (31.05.08 12:52) [1]
    > [0] ЗапомниСынок   (31.05.08 11:43)


    > С чем это может быть связано.

    с архитектурой и идеалогией системы.
  • LightRipple © (31.05.08 13:10) [2]
    > [0] ЗапомниСынок   (31.05.08 11:43)
    > С чем это может быть связано.

    С неправильной реализацией.
    Была статья про Hook`и. Поищи ее.
  • ЗапомниСынок (31.05.08 13:50) [3]
    Собственно проблема проблемой является только при отладке. Когда не удается повторно скомпилировать файл, приходится перезагружать систему.

    2 LightRipple
    Может вы мне еще подскажите в чем заключается неправильная реализация.
  • LightRipple © (31.05.08 13:56) [4]
    > [3] ЗапомниСынок   (31.05.08 13:50)
    > Может вы мне еще подскажите в чем заключается неправильная реализация.

    IHMO, в работе с глобальными переменными.
    Позволю себе повториться: поищи статью.
    Вроде она была на этом форуме. Не помню :(
  • guav © (31.05.08 14:04) [5]
    А где обещали мгновенную выгрузку ?
  • LightRipple © (31.05.08 14:09) [6]
    > [5] guav ©   (31.05.08 14:04)
    > А где обещали мгновенную выгрузку ?

    А про мгновенную я ничего не говорила :)
  • Leonid Troyanovsky © (31.05.08 15:03) [7]

    > ЗапомниСынок   (31.05.08 11:43)  

    > из адресного пространства каких-то процессов. С чем это
    > может быть связано.

    Dll c обычными хуками не выгружаются сразу после снятия оных.
    Им требуется еще, чтобы в зацепленном потоке произошло еще
    одно отлавливаемое событие. Например, для WH_GETMESSAGE
    это Post(Thread)Message.

    Возможно, что и в случае WinHook требуется нечто подобное.
    Можно попробывать генирировать кустомное сообщение.

    Да, и еще [4]. И так делать не надо:

    > case dwReason of
    >   DLL_PROCESS_ATTACH:
    >      hLogWin := FindWindow(...)

    hLogWin, то можно, например, найти его при первом
    вызове HookProc.
     
    > {$R *.res}
    Это какие такие ресурсы?

    --
    Regards, LVT.
  • Leonid Troyanovsky © (31.05.08 15:05) [8]

    > Leonid Troyanovsky ©   (31.05.08 15:03) [7]

    > Можно попробывать генирировать кустомное сообщение.

    В смысле - событие, sorry.

    --
    Regards, LVT.
  • ЗапомниСынок (02.06.08 09:53) [9]
    2 LightRipple
    Прежде чем давать ответ на вопрос, можно было хотя бы взглянуть на код. Вы путаете функции SetWinEventHook и SetWindowsHookEx. Во втором случае дескриптор Hook-а требуется для корректного
    вызова CallNextHookEx. В первом случае этого не требуется, поэтому и выделять общую область памяти при момощи CreateFileMapping не нужно.

    2 Leonid Troyanovsky
    Ясно, примерно так я и думал. Спасибо. Проблема собственно заключается в том, что после установки hook-а становится невозможным продолжать разработку программы. поскольку dll не удается скомпилировать заново. Приходится либо перегружать систему, либо идти пить чай, поскольку через некоторое время библиотека выгружается.

    {$R *.res}
    Осталось после генерации библиотеки средой :) Вы правы.

    >> case dwReason of
    >>   DLL_PROCESS_ATTACH:
    >>      hLogWin := FindWindow(...)

    >hLogWin, то можно, например, найти его при первом
    >вызове HookProc.

    Можно, причем не находить, а просто передавать в функцию SetHook, но тогда как раз придется выделять общую память, чтобы предоставить доступ к этому hLogWin всем экземплярам dll.
    Предполагается, что Hook устанавливается/снимается при создании/уничтожении окна FindWindow(...), т.е. окно заведомо существует, поэтому не вижу здесь ничего криминального. Вопрос разве что в скорости, может вы и правы.
  • LightRipple © (02.06.08 11:47) [10]
    > [9] ЗапомниСынок   (02.06.08 09:53)
    > Прежде чем давать ответ на вопрос, можно было хотя бы взглянуть на код.
    > Вы путаете функции SetWinEventHook и SetWindowsHookEx.

    Sorry. Действительно, невнимательна :(
  • Leonid Troyanovsky © (02.06.08 18:42) [11]

    > ЗапомниСынок   (02.06.08 09:53) [9]

    > окна FindWindow(...), т.е. окно заведомо существует, поэтому
    > не вижу здесь ничего криминального. Вопрос разве что в скорости,
    >  может вы и правы.

    Во-ще-то, я имел ввиду
    http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx

    Т.е., все отклонения от генерального курса должны быть
    тщательно обдуманы и обоснованны.

    Сомнительным в одноразовой передаче хендла приемника
    является участок от начала HookProc до PostMessage.
    Возможно, что PostThreadMessge здесь более предпочтителен.

    > Приходится либо перегружать систему

    Думаю, что хватит и логофа.

    --
    Regards, LVT.
Есть новые Нет новых   [134433   +21][b:0][p:0]