SetWinEventHook с CreateProcess, переполнение стека

Я открываю окно с CreateProcess, и у меня много проблем с пониманием SetWinEventHook.

В вызывающей функции у меня есть:

HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT );

BOOL result = CreateProcess(0, arguments,
NULL, NULL, FALSE, 0, NULL,
NULL, &StartupInfo, &ProcessInfo)

if (hook) {
UnhookWinEvent(hook);
}

Процесс создания завершается без помех, но функция WinEventProc, связанная с SetWinEventHook, не вызывается. Чтобы получить вызов WinEventProc, я попробовал что-то вроде этого:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0);

после вызова createProcess, но я не знаю, как завершить цикл while, чтобы он шел непрерывно.

Я много читал, но я не понимаю, как использовать SetWinEventHook, чтобы поймать процесс, запущенный CreateProcess. Любая помощь приветствуется!

2

Решение

Возможно, вам нужен полный и работающий цикл обработки событий — попробуйте:

MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Если ваше приложение не является приложением с графическим интерфейсом — или, более конкретно, если вам не нужен цикл обработки событий для чего-то еще, кроме хуков, — вы можете либо добавить другой поток и использовать вышеупомянутый цикл обработки событий там (и, я полагаю, все перехватывания и отсоединения) или используйте PeekMessage в сочетании с GetMessage создать неблокирующий цикл обработки событий и регулярно вызывать его.

Во-вторых, вы не должны снимать хук сразу после звонка CreateProcess, Обычно создание окна происходит после полной загрузки и инициализации программы, и этот процесс может занять некоторое время. CreateProcess работает асинхронно, что означает, что он не ждет, пока все это произойдет, прежде чем выйти.

В-третьих, чтобы иметь возможность получать любые сообщения о перехватах, ваш цикл сообщений должен выполняться между SetWinEventHook а также UnhookWinEvent — в любом другом случае вы ничего не получите.

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

В целом это должно выглядеть следующим образом:

BOOL result = CreateProcess(0, arguments,
NULL, NULL, FALSE, CREATE_SUSPENDED, NULL,
NULL, &StartupInfo, &ProcessInfo);

HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, WinEventProc, ProcessInfo.dwProcessId, 0, WINEVENT_OUTOFCONTEXT );

ResumeThread(ProcessInfo.hThread);

// If you don't have an event loop function in your application already, then you could insert a temporary one here.
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Если ваше приложение не управляется событиями — просто обычное последовательное приложение, то вам следует регулярно вызывать вышеуказанный цикл обработки событий до тех пор, пока WinEventProc выполняется — вы, вероятно, должны добавить некоторые защитные переменные, чтобы увидеть, было ли оно уже выполнено. Другой хорошей идеей может быть включение некоторого тайм-аута (2-3 минуты?) На случай, если события не публикуются (сбой приложения, приложение по какой-либо причине не создает объектов). Для простоты я также пропустил любую проверку ошибок.

И ваша процедура подключения должна сделать что-то вроде этого:

void CALLBACK WinEventProc(
HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime)
{
// This will handle the re-entrance problem nicely.
UnhookWinEvent(hWinEventHook);

// Do wathever you need to do with a window here.
[...]

}

РЕДАКТИРОВАТЬ:

Что касается пропуска через цикл сообщений — да, именно это и должен делать этот цикл сообщений.

Какой цикл обработки сообщений вам больше подходит, зависит от конструкции вашей программы — если у вас уже работает четный цикл (GUI-фреймворки, такие как Qt, MFC … обычно уже реализуют его для вас), то вам не нужно добавлять его в любом случае , Если вы хотите, чтобы ваше приложение дождалось доставки WinEvent, вам следует сделать что-то вроде этого:

//Global variable for stop-condition:
bool docontinue = false;

void CALLBACK WinEventProc(
HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime)
{
// This will handle the re-entrance problem nicely.
UnhookWinEvent(hWinEventHook);

// Do wathever you need to do with a window here.
[...]
docontinue = false;
}

И функция перехвата должна делать:

// In hooking function use:
docontinue = true;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (!docontinue)
break;
}

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

4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector