Как подключить внешний процесс к SetWindowsHookEx и WH_KEYBOARD

Я безуспешно пытаюсь зацепить, например, Блокнот. Кажется, что создание глобального крючка работает нормально.

Тестирование на XP SP2.

Изменить: исправленный код теперь работает.

Код MyDLL

#include <windows.h>
#include <iostream>
#include <stdio.h>

HINSTANCE hinst;
#pragma data_seg(".shared")
HHOOK hhk;
#pragma data_seg()
//#pragma comment(linker, "/SECTION:.shared,RWS") compiler error in VC++ 2008 express

LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam) {  
    if (code < 0) {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    Beep(1000, 20);
    return CallNextHookEx(hhk, code, wParam, lParam);
}

extern "C" __declspec(dllexport) void install(unsigned long threadID) { 
    hhk = SetWindowsHookEx(WH_KEYBOARD, wireKeyboardProc, hinst, threadID);
}
extern "C" __declspec(dllexport) void uninstall() {
    UnhookWindowsHookEx(hhk); 
}

BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) {
    hinst = hinstDLL;
    return TRUE;
}

Моя программа

#include <Windows.h>

unsigned long GetTargetThreadIdFromWindow(char *className, char *windowName)
{
    HWND targetWnd;
    HANDLE hProcess;
    unsigned long processID = 0;

    targetWnd = FindWindow(className, windowName);
    return GetWindowThreadProcessId(targetWnd, &processID);
} 

int _tmain(int argc, _TCHAR* argv[]) {
    unsigned long threadID = GetTargetProcessIdFromWindow("Notepad", "Untitled - Notepad");
    printf("TID: %i", threadID);    

    HINSTANCE hinst = LoadLibrary(_T("MyDLL.dll")); 

    if (hinst) {
        typedef void (*Install)(unsigned long);
        typedef void (*Uninstall)();

        Install install = (Install) GetProcAddress(hinst, "install");
        Uninstall uninstall = (Uninstall) GetProcAddress(hinst, "uninstall");

        install(threadID);

        Sleep(20000);

        uninstall();
    }

    return 0;
}

person s5804    schedule 04.05.2009    source источник


Ответы (1)


Три проблемы:

Вы используете идентификатор процесса, когда вам следует использовать идентификатор потока.

Ваш HHOOK должен перейти в общую память:

#pragma data_seg(".shared")
HHOOK hhk = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")

Вам необходимо передать свой HHOOK CallNextHookEx:

return CallNextHookEx( hhk, code, wParam, lParam);
person RichieHindle    schedule 04.05.2009
comment
GetWindowThreadProcessId () возвращает нужный вам идентификатор потока (в качестве возвращаемого значения). Что бы вы ни делали с встроенным ассемблером и ReadProcessMemory, в этом нет необходимости и почти наверняка не работает. - person RichieHindle; 05.05.2009
comment
вам также необходимо инициализировать hhk значением 0, иначе он не будет должным образом передан - person yoyoyoyosef; 17.06.2009
comment
@yoyoyoyosef: Спасибо - исправлено. - person RichieHindle; 17.06.2009
comment
Как бы то ни было, аргумент HHOOK для CallNextHookEx игнорируется во всех версиях Windows, более поздних, чем Windows 95; см. stackoverflow.com/questions/214022/ для получения дополнительной информации. - person Frerich Raabe; 29.02.2012
comment
Привет, Риччи. My Mainthread создает окна, я создаю другой поток и выполняю всю свою работу. (Это потому, что я пишу плагин для своего firefox, и плагины могут работать только в отдельных потоках, а не в Mainthread). Я настраиваю крючок из другого потока. Я делал WH_MOUSE_LL хук, но он улавливал события, даже когда мое приложение не было в фокусе. Я пробовал WH_MOUSE, когда идентификатор потока Mainthread настраивал слушателя, но при первом событии мыши (перемещении и т. Д.) Происходит сбой. Я сильно подозреваю, что это потому, что мой обратный вызов настроен вне потока? Вы тоже так думаете? - person Noitidart; 23.03.2016
comment
Я не использую DLL. Я определяю обратный вызов в выключенном основном потоке, а затем использую его для ловушки. Это сработало чудесно для LL. Но моя цель - получать события только тогда, когда мое приложение сфокусировано. Есть ли способ настроить хук WH_MOUSE с обратным вызовом из порожденного потока для окон с использованием идентификатора Mainthread? - person Noitidart; 23.03.2016
comment
@Noitidart: зависящий от потока хук WH_MOUSE должен быть определен в DLL, который будет внедряться и вызываться из контекста приложения, получающего событие мыши. Хук WH_MOUSE_LL не обязательно должен входить в DLL, он может быть только общесистемным. Одним из решений может быть использование WH_MOUSE_LL, а затем использование WindowFromPoint () и GetWindowThreadProcessId () для игнорирования сообщений, которые не предназначены для вашего целевого потока. - person RichieHindle; 24.03.2016
comment
Ах, большое спасибо за ваш ответ. Я исследую winwo с точки. :) - person Noitidart; 24.03.2016
comment
@RichieHindle - Я просто хотел убедиться - я хочу подключить собственное приложение только к WH_MOUSE, даже для этого мне понадобится DLL? - person Noitidart; 25.03.2016
comment
@Noitidart: В случае, когда вы подключаете свой собственный поток, я не думаю, что вам нужна DLL, но я не уверен на 100%. В случае, когда вы подключаете другой поток в одном и том же процессе, я также не знаю. - person RichieHindle; 26.03.2016
comment
Большое спасибо за информацию @RichieHindle! :) - person Noitidart; 26.03.2016