2017-10-27 1 views
1

콘솔 프로세스를 만든 다음 SetWinEventHook을 사용하여 이벤트를 모니터링하려고합니다. 내가 만든 프로세스와 관련된 PID를 사용하면 어떤 이벤트도 잡을 수 없습니다. pid/thread를 0/0 (모든 프로세스/스레드)로 설정하면 많은 결과가 발생합니다. 특정 프로세스에 연결하려고하는 방식에 문제가있는 것처럼 보입니다. 어떤 아이디어라도 감사 할 것입니다.WinEventHook이 특정 프로세스 ID의 이벤트를 수신하지 않습니다.

#include "stdafx.h" 
#include <windows.h> 
#include <Oleacc.h> 


DWORD CreateChildProcess(); 
void InitializeMSAA(DWORD pid); 
void ShutdownMSAA(); 
void SetConsoleBufferSize(DWORD processId, short columns, short rows); 
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 
    LONG idObject, LONG idChild, 
    DWORD dwEventThread, DWORD dwmsEventTime); 

HWINEVENTHOOK g_hook; 

int main() 
{ 
    DWORD pid = CreateChildProcess(); 
    Sleep(5000); 
    InitializeMSAA(pid); 
    MSG msg; 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

// Initializes COM and sets up the event hook. 
void InitializeMSAA(DWORD pid) 
{ 
    // Initializes Component Object Model library 
    CoInitialize(NULL); 

    g_hook = SetWinEventHook(
     EVENT_MIN, EVENT_MAX,  // Range of events (Console). 
     NULL,           // Handle to DLL. 
     HandleWinEvent,        // The callback. 
     pid, 0,    // Process and thread IDs of interest (0 = all) 
     WINEVENT_OUTOFCONTEXT); // Flags. 

    //| WINEVENT_SKIPOWNPROCESS 
} 

// Unhooks the event and shuts down COM. 
void ShutdownMSAA() 
{ 
    UnhookWinEvent(g_hook); 
    CoUninitialize(); 
} 

// Callback function that handles events. 
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 
    LONG idObject, LONG idChild, 
    DWORD dwEventThread, DWORD dwmsEventTime) 
{ 
    IAccessible * pAcc = NULL; 
    VARIANT varChild; 
    HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild); 
    if ((hr == S_OK) && (pAcc != NULL)) 
    { 
     BSTR bstrName; 
     pAcc->get_accName(varChild, &bstrName); 
     if (event == EVENT_SYSTEM_MENUSTART) 
     { 
      printf("Begin: "); 
     } 
     else if (event == EVENT_SYSTEM_MENUEND) 
     { 
      printf("End: "); 
     } 
     printf("%S\n", bstrName); 
     SysFreeString(bstrName); 
     pAcc->Release(); 
    } 
} 

// Creates a bash child process with i/o to a given console screen buffer 
DWORD CreateChildProcess() 
{ 
    // In order to launch bash in System32, program must be built as x64 
    LPCTSTR applicationAddress = L"C:\\Windows\\System32\\bash.exe"; 

    PROCESS_INFORMATION piProcInfo; 
    STARTUPINFO siStartInfo; 

    // Set up members of the PROCESS_INFORMATION structure. 
    SecureZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); 

    // Set up members of the STARTUPINFO structure. 
    // This structure specifies the STDIN and STDOUT handles for redirection. 
    SecureZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); 
    siStartInfo.cb = sizeof(STARTUPINFO); 

    // NB: Initial window size settings don't work for some reason. 
    auto minX = GetSystemMetrics(SM_CXMIN); 
    auto minY = GetSystemMetrics(SM_CYMIN); 
    siStartInfo.dwXSize = 200; 
    siStartInfo.dwYSize = 200; 
    //siStartInfo.dwXCountChars = 119; 
    //siStartInfo.dwYCountChars = 9; 

    //siStartInfo.wShowWindow = SW_HIDE; 
    siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE; 
    // | STARTF_USESHOWWINDOW | STARTF_USECOUNTCHARS 

    // Create the child process. 
    BOOL success = CreateProcess(
     applicationAddress, // absolute path to the application 
     TEXT("-i"),   // command line 
     NULL,    // process security attributes 
     NULL,    // primary thread security attributes 
     TRUE,    // handles are inherited 
     CREATE_NEW_CONSOLE,    // creation flags 
     NULL,    // use parent's environment 
     NULL,    // use parent's current directory 
     &siStartInfo,  // STARTUPINFO pointer 
     &piProcInfo);  // receives PROCESS_INFORMATION 


    if (!success) 
    { 
     int lastError = GetLastError(); 
    } 

    return piProcInfo.dwProcessId; 
} 
+0

notepad.exe로 시도했지만 ..... 모두 정상적으로 작동합니다. – Naidu

+0

그렇습니다. bash.exe와 cmd.exe가 모두 후크를 유발하지 않으므로 콘솔 앱에 문제가있는 것처럼 보입니다! – Catma

+0

possible ........ – Naidu

답변

2

나는, 나는 결코 캐치 이벤트를 생성 한 프로세스와 연관된 PID를 사용하는 경우.

그 이유는 콘솔 프로세스가 콘솔 창을 소유하지 않기 때문입니다. 콘솔 창은 conhost.exe (csrss.exe in versions of Windows prior to Win 7)와 연결됩니다. 따라서 콘솔 창과 관련된 메시지는 작성한 프로세스가 아니라 conhost.exe에 의해 처리됩니다.

pid/thread를 0/0 (모든 프로세스/스레드)로 설정하면 결과가 이됩니다.

시작한 콘솔 응용 프로그램과 관련된 conhost.exe 프로세스의 PID로 PID를 설정하십시오. 이제 콘솔 창에서만 이벤트를 수신해야합니다.

관련 conhost.exe 프로세스를 찾는 데 직접적인 API는 없다고 생각하지만 "conhost.exe"를 찾을 때까지 새 프로세스의 모든 하위 프로세스를 열거 할 수 있습니다. 이 주소는 CreateProcess()이 반환 된 직후에 conhost.exe가 나타나지 않으므로 반복적으로 수행해야합니다.

+0

특정 윈도우와 관련된 프로세스를 후킹하려는 경우'FindWindow()'또는'EnumWindows()'를 사용하여 윈도우를 찾거나'SetWindowsHookEx()'/'SetWinEventHook()'를 사용하여 시스템을 전역 적으로 생성 한 다음'GetWindowThreadProcessId()'를 사용하여 윈도우를 소유 한 프로세스 ID를 얻습니다. –

+0

@RemyLebeau 유감스럽게도 콘솔 창의 창 핸들에있는'GetWindowThreadProcessId'는 콘솔 창을 소유하지 않은 콘솔 프로세스의 PID를 반환합니다. – zett42

관련 문제