Lior Levin
Lior Levin

Reputation: 189

Terminate a child process with ctrl+c after CreateProcess in c++ (WinAPI)

I'm creating a process using the WinAPI's CreateProcessA() function and I'm trying to terminate the child process when the user presses the Ctrl+C keys, but all I can find on the msdn docs is the SetConsoleControlHandler, which in my understanding, sets the control handler to the current process, not a child process.

I'm looking for a way to set the control handler for a child process by using a handle to that process or something like this:

HANDLE hProcess;    // A handle to the child process after the CreateProcess function.

SetConsoleControlHandler(hProcess, myControlhandler, TRUE);

How can I do something like that?

Upvotes: 0

Views: 1863

Answers (1)

Drake Wu
Drake Wu

Reputation: 7190

If you want to use "Ctrl + C" in the parent process(console) to end the child process, you could call TerminateProcess in the handler routine callback function:

#include <Windows.h>
#include <iostream>
PROCESS_INFORMATION pi = { 0 };

BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
    switch (fdwCtrlType)
    {
        // Handle the CTRL-C signal. 
    case CTRL_C_EVENT:
        printf("Ctrl-C event\n\n");
        TerminateProcess(pi.hProcess, 0);
        return TRUE;
    default:
        return FALSE;
    }
}
int main()
{
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = true;

    BOOL ret = CreateProcess("C:\\Windows\\System32\\mspaint.exe", NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);

    SetConsoleCtrlHandler(CtrlHandler, true);
    WaitForSingleObject(pi.hProcess, -1);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
}

If you want to use "Ctrl+C" in the child process, you could monitor low-level keyboard input events:

#include <Windows.h>
#include <iostream>
PROCESS_INFORMATION pi = { 0 };
HHOOK hook;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HC_ACTION)
    {
        PKBDLLHOOKSTRUCT pkb = (PKBDLLHOOKSTRUCT)lParam;
        if (wParam == WM_KEYDOWN && pkb->vkCode == 'C')
        {
            if (GetAsyncKeyState(VK_CONTROL) < 0)
            {
                DWORD pid = 0;
                HWND hwnd = GetForegroundWindow();
                GetWindowThreadProcessId(hwnd, &pid);
                if (pid == pi.dwProcessId)
                {
                    TerminateProcess(pi.hProcess, 0);
                    PostQuitMessage(0);
                }
            }
        }
    }
    return CallNextHookEx(hook, code, wParam, lParam);
}
int main()
{
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = true;

    BOOL ret = CreateProcess("C:\\Windows\\System32\\mspaint.exe", NULL, NULL, NULL, false, 0, NULL, NULL, &si, &pi);

    hook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    WaitForSingleObject(pi.hProcess,-1);
    UnhookWindowsHookEx(hook);
    printf("unhook\n");
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
}

Upvotes: 3

Related Questions