0

I want to create an application that can control the window of specified running process. I'm using WINAPI to obtain the main window handle of desired application and the sending the messages to it via SendMessage function from WINAPI. But it seems like the applicetion does not react to the messages. There's my code:


#include <Windows.h>


struct handle_res {
    HWND hwnd;
    DWORD pid;
};

HWND vscode_hwnd;
DWORD vscode_thread_id;

BOOL CALLBACK enum_wnd_proc(HWND hwnd, LPARAM lparam)
{
    handle_res* p = reinterpret_cast<handle_res*>(lparam);
    DWORD pid{};
    if (GetWindowThreadProcessId(hwnd, &pid)) {
        if (p->pid == pid) {
            p->hwnd = hwnd;
            SetLastError(-1);
            return FALSE;
        }
    }
    return TRUE;
}

LRESULT CALLBACK wnd_proc(
    HWND hwnd,
    UINT msg,
    WPARAM wparam,
    LPARAM lparam
)
{
    SendMessageA(vscode_hwnd, msg, wparam, lparam);
    switch (msg) {
    case WM_DESTROY: { PostQuitMessage(0); } break;     
    default: return DefWindowProcA(hwnd, msg, wparam, lparam); break;
    }
    return 0;
}

int WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
)
{
    // obtain the window handle of the vscode
    STARTUPINFOA supinfo{};
    PROCESS_INFORMATION procinfo{};
    CreateProcessA(
        "C:\\vscode\\code.exe",
        NULL, NULL, NULL, FALSE,
        NORMAL_PRIORITY_CLASS,
        NULL, NULL, 
        &supinfo, &procinfo
    );

    handle_res res{};
    res.pid = procinfo.dwProcessId;
    EnumWindows(enum_wnd_proc, reinterpret_cast<LPARAM>(& res));
    vscode_hwnd = res.hwnd;
    vscode_thread_id = res.pid;
    
    // creating window for this application
    // to get messages and redirect them to the
    // obtained vscode window handle
    WNDCLASSA wndcls{};
    wndcls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wndcls.lpfnWndProc = wnd_proc;
    wndcls.hInstance = hInstance;
    wndcls.lpszClassName = "Window";

    if (!RegisterClassA(&wndcls)) {
        return -1;
    }

    HWND winh = CreateWindowA(
        "Window", "MyWindow", 
        WS_OVERLAPPEDWINDOW, 
        0, 0, 800, 600, 
        NULL, NULL, 
        hInstance, NULL
    );

    if (!winh) {
        return -1;
    }

    ShowWindow(winh, nCmdShow);
    MSG msg;
    while (GetMessageA(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }
    CloseHandle(procinfo.hProcess);
    CloseHandle(procinfo.hThread);
    return 0;
}

What should I do to make the running application react to the messages?

Asesh
  • 3,186
  • 2
  • 21
  • 31
  • 2
    Literally, **every single day** someone asks, how to automate a program by throwing random messages at it. The answer, to all of those question is: Don't. Use [UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32). – IInspectable Mar 19 '22 at 11:38
  • 1
    After calling CreateProcess(), you are not giving the new process enough time to create its window before you search for it. For instance, by calling [WaitForInputIdle()](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-waitforinputidle). And you are not checking if EnumWindows() was able to find the window before you start sending messages to it. – Remy Lebeau Mar 19 '22 at 16:03

0 Answers0