Handling processes interruption (CTRL+C, ::TerminateProcess, WM_CLOSE) in console applications spawned with CreateProcess

*** QUESTIONS IS IN LINUX SECTION TOO BY ERROR! I APOLOGIZE , THIS APPLIES TO WINDOWS API ***

Dear Experts,

I'm struggling with a weird scenario, I'll try to explain everything, let's see if there's a guru out-there able to show me the way....

I've a console-based application, it may be run as a windows service or as a console application, but it also may be spawned by another application using CreateProcess with hidden console Window.
If I want to terminate cleanly the application, I can stop the service (when running as service), I can type CTRL+C in the console window and trap the SIGINT signal (when as a console), I can also install a ControlHandler and trap the console close (when as a console), but when spawning it with CreateProcess, I cannot find a reliable way to terminate it cleanly.
From the documents I read, the ::TerminateProcess API sends a WM_CLOSE , that is obviously ignored by a console application, and there're people out there suggesting to install an event pump inside the console application to handle WM_CLOSE. Well, I'm lost...The solution seams to be to spawn an hidden thread with an hidden window and it's own message pump, but I cannot find a "WORKING" and "COMPLETE" example on the web.

Help ?
benaclerAsked:
Who is Participating?
 
jkrConnect With a Mentor Commented:
>>From the documents I read, the ::TerminateProcess API sends a WM_CLOSE ,
>>that is obviously ignored by a console application

Err, no, that is not the case. 'TerminateProcess()' simply kills the process right away without sending a message.

>>The solution seams to be to spawn an hidden thread with an hidden window
>>and it's own message pump, but I cannot find a "WORKING" and "COMPLETE"
>>example on the web.

You mean something like
#include <windows.h>
 
#pragma comment(lib,"user32.lib")
 
static char g_szClassName[] = "MyWindowClass";
static HINSTANCE g_hInst = NULL;
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
  switch(Message)
  {
     case WM_ACTIVATE:
     OutputDebugString("WM_ACTIVATE!\n");
     break;
     case WM_CLOSE:
        DestroyWindow(hwnd);
     break;
     case WM_DESTROY:
        PostQuitMessage(0);
     break;
     default:
        return DefWindowProc(hwnd, Message, wParam, lParam);
  }
  return 0;
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  LPSTR lpCmdLine, int nCmdShow)
{
  WNDCLASSEX WndClass;
  HWND hwnd;
  MSG Msg;
 
  g_hInst = hInstance;
 
  WndClass.cbSize        = sizeof(WNDCLASSEX);
  WndClass.style         = NULL;
  WndClass.lpfnWndProc   = WndProc;
  WndClass.cbClsExtra    = 0;
  WndClass.cbWndExtra    = 0;
  WndClass.hInstance     = g_hInst;
  WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  WndClass.lpszMenuName  = NULL;
  WndClass.lpszClassName = g_szClassName;
  WndClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
 
  if(!RegisterClassEx(&WndClass))
  {
     MessageBox(0, "Window Registration Failed!", "Error!",
        MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
     return 0;
  }
 
  hwnd = CreateWindowEx(
     WS_EX_CLIENTEDGE,
     g_szClassName,
     "The title of my window",
     WS_OVERLAPPEDWINDOW,
     CW_USEDEFAULT, CW_USEDEFAULT, 320, 240,
     NULL, NULL, g_hInst, NULL);
 
  if(hwnd == NULL)
  {
     MessageBox(0, "Window Creation Failed!", "Error!",
        MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
     return 0;
  }
 
  ShowWindow(hwnd, SW_HIDE); // hide window <-----------
  UpdateWindow(hwnd);
 
  while(GetMessage(&Msg, NULL, 0, 0))
  {
     TranslateMessage(&Msg);
     DispatchMessage(&Msg);
  }
  return Msg.wParam;
}

Open in new window

0
 
benaclerAuthor Commented:
You're right about TerminateProcess. I just explained it in the wrong way, let's say that the API I'm using may send a WM_CLOSE to the process instead of killing it brutally.

Now, about your code, it should be moved in a separate thread right ?
0
 
jkrCommented:
Actually no, that should be the main thread from which you spawn your worker thread (e.g. upon receiving 'WM_ACTIVATE')
0
 
jkrCommented:
Any further problems?
0
 
benaclerAuthor Commented:
It's working. I don't know why It didn't work before, but it's working now, so I accept your solution.
Thanks.
0
All Courses

From novice to tech pro — start learning today.