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?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
>>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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.