I'm trying to wrap basic windows process functionalities in a Process Class. I want the processes to run in the same process group and same console of the parent, and I want to kill them gently when I call Process::Kill();
Reading from various sources I've ended up with this code, which first checks if the process is a GUI, if so sends a WM_CLOSE (the EnumChildWindowsHandler does it), if not, and the process has a console, sends a CTRL_C event. It works, but when the child Process is the "cmd.exe" the procedure crashes on the GenerateConsoleCtrlEvent function and the debugger says an access violation on write happened.
What's the point? What didn't I understand in my readings?
bool Process::Kill( ) {
// Here I check if the process is a GUI app
if (!EnumThreadWindows(mChildInfo->dwThreadId, EnumChildWindowsHandler, mChildInfo->dwProcessId)) {
if (WaitForSingleObject(mChildInfo->hProcess, 2000) == WAIT_TIMEOUT) {
{ TerminateProcess(mChildInfo->hProcess, 0); } }
//If not, test if it's a CUI then send CTRL_C
else {
int minPid = 10;
int els;
unsigned long *pids = new unsigned long(minPid);
els = GetConsoleProcessList( pids, minPid );
if (els > minPid) {
free (pids);
pids = new unsigned long(els);
els = GetConsoleProcessList(pids, els);
}
if (find(pids, pids+els, mChildInfo->dwProcessId)) {
cout << "Sending CTRL_C_EVENT.." << endl;
SetConsoleCtrlHandler(NULL, TRUE);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
if (WaitForSingleObject(mChildInfo->hProcess, 2000) == WAIT_TIMEOUT) { TerminateProcess(mChildInfo->hProcess, 0); }
SetConsoleCtrlHandler(NULL, FALSE);
CloseHandle(mChildInfo->hProcess);
CloseHandle(mChildInfo->hThread);
}
return true;
}
EDIT: I've found the ReactOS cmd.exe source code which is gold for this sort of thing. I'll post updates from what I eventually learn. Url: http://doxygen.reactos.org/db/d4f/base_2shell_2cmd_2cmd_8c_source.html
The cmd source code explains well how to do correctly, BTW I just use the CTRL_BREAK and works like a charm. In the create process I pass CREATE_NEW_PROCESS_GROUP and I set the SW_SHOWDEFAULT for the showWindow mode, and then I kill processes this way:
Also, if we want to act in a cmd like way while handling signals, we can register a sighandler like this (we still nedd the WriteConsoleInput):
The main thread enters the critical section while waiting for the termination for the process just started.
BTW I still don't know why my application was crashing with the previous code.