Win32 application without windows - wait for the program to exit

I have a windowless application whose sole purpose is to install a 32-bit DLL file with a hook and wait for the completion of the parent program (64-bit program). A 64-bit program is written in C #, and a windowless application is written in C ++. Initially, I had this GetMessage loop in which the program was opened:

while(GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } 

I closed the C ++ application using the Process.Kill method in C #, but I found out that this does not allow closing the C ++ application. Also, if a C # application crashes, the C ++ application will remain open forever. I did a C ++ application check to see if a C # application was working all using this loop:

 while(true) { if(PeekMessage(&msg, NULL, 0, 0, true)) { TranslateMessage(&msg); DispatchMessage(&msg); } if(!isMainProgramRunning()) break; Sleep(1000); } 

For some reason, Sleep causes problems. The hooks set by the DLL file are WH_CBT and WH_KEYBOARD. Whenever I press a key when a C ++ application is working with this loop, the keys just eat it. Removing sleep makes it work fine, but, as expected, it uses 100% CPU , which I don't want. I tried to completely delete the message loop and instead use WaitForSingleObject with an infinite timeout in the thread, which will end when isMainProgramRunning returns false. This basically blocks the entire computer.

I really donโ€™t understand why GetMessage, which, as I saw it, never returned, but suspended the main thread indefinitely, has not yet caused these problems. WaitForSingleObject makes each application freeze when I click on it. How can I make a C ++ application remain open until the C # application closes?

Edit:

Since I was told that sleeping in a pump message is bad, let me ask: is there a way to indicate the waiting time for a waiting message, so the program does not wait indefinitely for a message, but rather, it will wait about 250 ฮผs, timeout, let me run isMainProgramRunning method, and then wait again?

Edit2:

I tried using MsgWaitForMultipleObjects, although in a slightly different way than Leo suggested. This is the loop I used:

 while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED) { if(PeekMessage(&msg, NULL, 0, 0, true)) { TranslateMessage(&msg); DispatchMessage(&msg); } if(!isMainProgramRunning()) break; } 

Again I had the same problem with Sleep. I also tried to pause the main thread and resume it. Same problem. What does GetMessage do that allows it to wait without causing these problems? Maybe this should be the subject of another message, but why is it that when a C ++ application setting hooks is sleeping or paused, all hook processing is also paused?

Edit3:

Here is the DLL method that a C ++ application calls to install hooks:

 extern "C" __declspec(dllexport) void install() { cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL); if(cbtHook == NULL) MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK); keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL); if(keyHook == NULL) MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK); } 
+4
source share
4 answers

GetMessage never returns because you don't have a window!

To use the message queue, you must have some kind of graphical interface. You can, for example, create a hidden window.

0
source

You have two separate problems:

  • How to make a windowless program work in C ++ automatically if a C # program terminates (for example, a crash).

    In a C ++ program, open the C # program handle. Because a C # program runs a C ++ program, a C # program passes its own PID as an argument; a C ++ program can then open the handle to this process using OpenProcess .

    Then use MsgWaitForMultipleObjects in your message loop. If the C # program terminates with a descriptor, you will have to signal and you wake up. (You can also use WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 to check if the process is signaling or not, for example, to check why you were woken up, although the result of MsgWaitForMultipleObjects will also tell you about it.)

    You must close the process descriptor when you exit (although the OS will do this for you when you exit, it is good practice if you reuse this code in a different context). Note that the handle displays the process that it represents, and that is why you can wait for it.

  • How to make a C # program output a C ++ program.

    You may not need this if you get # 1, but you can just run the C # program in C ++ if you want.

    DO NOT use PostQuitMessage and DO NOT send or send WM_QUIT through threads or processes.

    Instead, post another message stating that both applications agree (e.g. WM_APP + 1) using PostThreadMessage .

+4
source

You can create a named event and use:

MsgWaitForMultipleObjects

in your message loop.

A C # application should open and raise this event in order to inform your application about the exit.

This is a kind of minimal interprocess communication.

+1
source

You must exit the process by posting the WM_QUIT message and processing it correctly, as indicated in this article (modality) , Raymond Chen. Do not sleep inside a loop without processing messages - this is wrong. Your application must either process the message or wait for new messages.

0
source

Source: https://habr.com/ru/post/1332721/


All Articles