Сбой SetWindowsHookEx в Google Chrome. Код ошибки 87 недопустимый параметр

#c #windows #winapi #setwindowshookex

#c #Windows #winapi #setwindowshookex

Вопрос:

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

Мой код подключения работает для большинства приложений, кроме Google Chrome. Я сократил свой код до следующего, чтобы вы могли видеть, что все идет неправильно.

Main.cpp

 #include <Windows.h>
#include <iostream>
#include <psapi.h>
#include <Tlhelp32.h>

unsigned long GetProcId( const std::stringamp; name )
{
    unsigned long res = 0 ;

    HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 processInfo ;
    processInfo.dwSize=sizeof(PROCESSENTRY32W);

    if( !Process32First( hSnapShot, amp;processInfo ) )
    {
        CloseHandle( hSnapShot ); 
        return res ;
    }

    do 
    {
        if( NULL != ( strstr ( strlwr ( processInfo.szExeFile ), name.c_str() ) ) )
        {               
            res = processInfo.th32ProcessID ;
            break ;
        }
    } while(Process32Next( hSnapShot,amp;processInfo ));

    CloseHandle( hSnapShot ) ;
    return res ;
}

typedef LRESULT (CALLBACK *DllHookProc)(int nCode, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
               LPSTR lpCmdLine, int nCmdShow)
{
    unsigned int processid = GetProcId( "chrome.exe" ) ;

    if (processid == 0)
    {
        return 0 ;
    }

    HINSTANCE dllInstance = LoadLibrary("mydll.dll") ;

    if (dllInstance == NULL)
    {
        return 0 ;
    }

    DllHookProc hookProc = (DllHookProc)::GetProcAddress(dllInstance, "HookProc");

    if ( hookProc == NULL) 
    {
        FreeLibrary(dllInstance);
        return 0 ;
    }

    HHOOK hook = SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)hookProc,
        dllInstance, processid );

    if (hook == NULL)
    {
        FreeLibrary(dllInstance);
        return 0 ;
    }

    return 0 ;
}
  

Тестовая Dll (mydll.dll )

 LRESULT CALLBACK HookProc (int nCode, WPARAM wParam, LPARAM lParam )
{
    //Pass to the next chain in the process list
    return CallNextHookEx( 0, nCode, wParam, lParam);
}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    return TRUE;
}
  

Файл определения

 LIBRARY "MYDLL"
EXPORTS
HookProc @1
  

Все работает нормально (включая получение ProcessId и загрузку библиотеки и getprocaddress) вплоть до SetWindowsHookEx, который возвращает NULL с кодом ошибки 87 (недопустимый параметр).

Оба chrome.exe и мой код являются 32-разрядными.

Работает ли это у кого-нибудь еще или кто-нибудь знает, что это не работает?

Спасибо

Ответ №1:

Вы понимаете, что chrome использует многопроцессорную модель, верно? Многие экземпляры Chrome взаимодействуют, и у некоторых из них может не быть очереди событий.

Скорее всего, ваш GetProcId код не будет работать в Chrome, потому что он находит только один соответствующий процесс.

Ответ №2:

Одна из возможных проблем может заключаться в том, что вы создаете 64-битный код, но chrome.exe он 32-битный (или наоборот). [Смотрите комментарий и обновление, это не тот случай.]


Одна подозрительная вещь в вашем коде заключается в том, что вы не вызываете Process32First , и это, похоже, требуется. Смотрите, например: Создание моментального снимка и просмотр процессов.


Последнее предложение: вы передаете идентификатор процесса в SetWindowsHookEx , но при этом ожидается идентификатор потока.

Комментарии:

1. Спасибо за ответ, но они оба 32-разрядные

2. Исправлена ошибка с Process32First. Я исправил код, но, к сожалению, проблема все та же. Еще раз спасибо

3. Это решило проблему, большое спасибо! Однако в Chrome потенциально запущено много потоков, поэтому есть ли способ, которым я могу найти идентификатор основного потока GUI, чтобы я знал, что моя dll не будет выгружена, пока они не выйдут из chrome? Еще раз спасибо, вы оказали большую помощь

4. Извините, не знаю об этом — на самом деле я не программирую в Windows 🙂 Задайте отдельный вопрос.

5. «Однако в Chrome потенциально запущено множество потоков, поэтому есть ли способ, которым я могу найти идентификатор основного потока графического интерфейса» — лучшее, что можно сделать, это найти HWND в Chrome, который вас интересует, и использовать GetWindowThreadProcessId, чтобы получить идентификатор этого потока. Также рекомендую использовать Spy , чтобы проверить, как структурированы окна и каким процессам / потокам они принадлежат, но имейте в виду, что Chrome может изменить способ их работы на каком-то этапе в будущем. На данный момент похоже, что все HWND в chrome принадлежат одному потоку, за исключением некоторых окон плагинов.