Win32 windowless application - wait for program exit - c++

I have a windowless application whose only purpose is to install a 32 bit hook DLL file and wait until the parent program (a 64-bit program) exits. The 64-bit program is written in C#, and the windowless application is written in C++. I originally had this GetMessage loop which held the program open:
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
I was closing the C++ application using the Process.Kill method in C#, but I found out that that isn't allowing the C++ application to close cleanly. Also, if the C# application crashed, the C++ application would stay open forever. I made the C++ application check to see if the C# application is still running, using this loop:
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
Sleep(1000);
}
For some reason the Sleep causes problems. The hooks installed by the DLL file are WH_CBT and WH_KEYBOARD. Whenever I press a key while the C++ application is running with this loop, the keys just get eaten up. Removing the Sleep makes it work fine, but, as expected, it uses 100% CPU, which I don't want. I tried removing the message loop altogether and instead using WaitForSingleObject with an infinite timeout on a thread which would end when isMainProgramRunning returned false. This basically locks up the whole computer.
I don't really understand why GetMessage, which, as far as I saw, never returned, but suspended the main thread indefinitely, didn't cause these problems yet WaitForSingleObject causes every application to freeze when I click on it. How can I get the C++ application to stay open until the C# application closes?
Edit:
Since it's been pointed out to me that sleeping in a message pump is bad, let me ask this: Is there a way to specify a timeout on the message waiting, so the program isn't waiting indefinitely for a message, but rather, will wait about 250 ms, timeout, let me run the isMainProgramRunning method, then wait some more?
Edit2:
I tried using MsgWaitForMultipleObjects, although in a somewhat 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 the Sleep. I also tried suspending the main thread and having the other thread resume it. Same problem. What is it that GetMessage does that allows it to wait without causing these problems? Maybe this should be the subject of another post, but why is it that when the C++ application installing the hooks sleeps or is suspended, all processing in the hooks seems to suspend as well?
Edit3:
Here is the DLL method that the C++ application calls to install the 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);
}

You have two separate problems:
How to make the windowless C++ program exit automatically if the C# program exits (e.g. crashes).
In the C++ program, open a handle to the C# program. Since the C# program runs the C++ program, have the C# program pass its own PID as an argument; the C++ program can then open a handle to that process using OpenProcess.
Then use MsgWaitForMultipleObjects in your message loop. If the C# program exits the handle you have to it will be signalled and you will wake up. (You can also use WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 to check if the process is signalled or not, e.g. to verify why you were woken up, although the MsgWaitForMultipleObjects result will tell you that as well.)
You should close the process handle as you are exiting (although the OS will do it for you when you exit, it's good practice in case you re-use this code in a different context). Note that the handle outlives the process it represents, and that is why you can wait on it.
How to make the C# program instruct the C++ program to exit.
You may not need this if you get #1 working, but you could just have the C# program post a message to the C++ one if you want.
Do NOT use PostQuitMessage and do NOT post or send WM_QUIT across threads or processes.
Instead, post some other message that the two apps agree on (e.g. WM_APP+1) using PostThreadMessage.

You can create a named event and use:
MsgWaitForMultipleObjects
in your message loop.
The C# application only have to open and raise this event to tell your application to exit.
It's kind of minimal interprocess communication.

You should exit the process by posting a WM_QUIT message to it and handling it correctly, as specified in this article (Modality), by Raymond Chen. Don't sleep inside a loop without handling messages - it's wrong. Your app should either be handling a message or waiting for new messages.

GetMessage never returns is because you don't have a window created!
To use a message-queue you have to have some GUI. You Can for instance create a hidden window.

Related

Program stopps working at GetMessage() function

I'm pretty new to the Hook-Stuff and I'm trying to learn how to work with it. When I learn new stuff I usually copy Code from the Internet and see if it works - if yes i go into detail and search everything up. So with all Codes I tried I have the same issue. They stop working at the GetMessage() function. I'm working with Visual Studio - I debugged it and when it reaches the function it just does nothing but stays on it.
I tried it with several Codes - for example this one:
HMODULE lib = LoadLibrary("C:\\Users\\A\\Desktop\\Dll1.dll");
if (lib) {
HOOKPROC procedure = (HOOKPROC)GetProcAddress(lib, "_procedure#12");
if (procedure)
hook = SetWindowsHookEx(WH_CALLWNDPROC, procedure, lib, 0);
else
printf("Can't find function in dll!\n");
}
else
printf("Can't find dll!\n");
if (hook)
printf("Hook installed properly!\n\n");
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
FreeLibrary(lib);
UnhookWindowsHookEx(hook);
It prints "Hook installed properly!" and does nothing! The code is from http://www.rohitab.com/discuss/topic/41238-global-hooks-to-intercept-windows-messages/
Unlike a mouse/keyboard hook, a window procedure hook runs in the context of a hooked thread that calls a window procedure. It does not delegate back to the thread that installed the hook, like you are expecting. That is why a window procedure hook must exist in a DLL when hooking other processes - the DLL gets injected into the address space of a hooked process, and then the hook is called by any hooked thread before/after it passes a message to a window procedure.
Your program that is installing the hook has no windows of its own, so no messages are being received. That is why GetMessage() blocks your app indefinitely. You would need to add a UI to your app, or have your hook manually post/send its own message back to your app using (Post|Send)Message() or PostThreadMessage(), in order to unblock GetMessage().
Your program is not going to receive messages unless it creates windows, hooks are delivered as part of the hooked program's message loop (that is why the hook function needs to be in a DLL for this situation).
The message queue is specific to the thread that created the window, posted messages are always going to be received on the thread that created the window, that is simply the way Windows operates.

DLL crashes app after reuse

I use an application that uses mdi and a script can be attached to, and detached from, a mdi window to be run/stopped on demand; this script loads my dll that does some work; it does fine so; however, when I detach the script still all is fine and the application should unload the dll (and it calls dllmain with the appropriate thread_attach/detach and process_attach/detach operations). Now if I try to re-attach the script to the winow, or to attach it to another window, after the dll has been in use once - the main application crashes. I have isloated the problem to a thread that is created by the dll; the tread crates a window; so, I create the thread like so:
if (!hThread) hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
and, when the script is detached it shuts down the thread like so (no matter if the commented-out lines are uncommented-out):
SendMessage(hWnd, WM_DESTROY, 0, 0);
//TerminateThread(hThread, 0);
//WaitForSingleObject(hWndThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
I'm at a loss here as to why the main app crashes. A different thread (i.e. one that would simply sleep for a second and loop, will do no harm. What gives?
Ok, here are some ideas:
You said your thread opens a window. Do you run a message loop in the thread function, or you expect your window to be serviced by some other message loop?
If you are running your own message loop in the thread, then exiting the loop may or may not happen, depending on how you have written it. If you use something like:
while(GetMessage(&msg, ...) // msg loop in the thread function
{
....
}
DestroyWindow(hWnd); // see comment below
then this requires a WM_QUIT and not WM_DESTROY to exit. Anyway, the best is to send your window a WM_QUIT and after exiting the message loop then call DestroyWindow() to destroy it properly.
Quoting from MSDN:
DestroyWindow function
Destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain
After posting WM_QUIT message to your window, your main thread should wait for the window thread to exit. Here is some relevant code:
SendMessage(hWnd, WM_QUIT, 0, 0); // send your quit message to exit the msg loop
if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) // wait up to 5 seconds
{
TerminateThread(hThread, -1); // bad! try to never end here
}
I hope this helps. I use this in a threaded log viewer that uses a window to display log messages.

How do you create a Message Box thread?

I have tried doing things like...
const char *MessageBoxText = "";
DWORD WINAPI CreateMessageBox(LPVOID lpParam){
MessageBox(NULL, MessageBoxText, "", MB_OK|MB_APPLMODAL);
return TRUE;
}
MessageBoxText = "Blah, Blah, Blah...";
CreateThread(NULL, 0, &CreateMessageBox, NULL, 0, NULL);
However, this does not seem to work correctly for the task I am trying to perform.
What is the best way to create a thread for a message box, without having it glitch up?
Consider passing message text as thread parameter instead of global variable, to make code thread-safe.
DWORD WINAPI CreateMessageBox(LPVOID lpParam) {
MessageBoxA(NULL, (char*)lpParam, "", MB_OK);
return 0;
}
CreateThread(NULL, 0, &CreateMessageBox, "Blah, Blah, Blah...", 0, NULL);
Also, you don't need to specify MB_APPLMODAL as it's default flag (it equals to 0).
If you are targeting modern Windows OS, it's better to have UNICODE defined, because MessageBoxA will convert you strings to UTF-16 and call MessageBoxW
What is the best way to create a thread for a message box, without having it glitch up?
In general, you don't.
Under Windows, all the windows (small 'w', meaning individual GUI elements here) in an application "run" in a single thread. This is generally the "main" thread -- but in particular, it is the thread in which the message pump is running. See my linked post for more details on the message pump.
If what you are truly trying to achieve is a dialog box or some other kind of window that can run concurrently to other windows running, so that it can remain up while other windows are still responsive to user input, then you want a modeless window or dialog box. This is a window that doesn't block other windows from processing updates or accepting user input. See here for a description of how to implement this using MFC, but note that you don't need to use MFC in order to implement a modeless dialog box.
Old question, new answer...
If the thread being invoked is being called into existence by a process that immediately exits (say you're running an executable that uses a VC++ DLL which pops a message box) then the thread will never have a chance to execute.
I had created a VC++ executable for testing that ran a loadlibrary on my DLL and the DLL created various threads with debugging message boxes. Since my testing executable only called the DLL and then exited, it didn't work.
I was informed by a coworker that I needed to add a sleep to the end of the testing executable that is using the DLL file in order for it to work.
Sure enough, it fixed it. This makes sense too, especially in the context of a DLL. Most applications loop until instructed to exit; my test application did not.
Be mindful of how your application is behaving!

Can I use my own message loop in windows?

I am building a C++ program, on windows, using Visual Studio. It relies on a COM base API, that sends windows message for notification.
To process those messages, I see two possibilities:
Create a windows form and call doModal on it which should process the messages, but since I don't want to use any UI, it's not what I want to do
make my own loop for processing messages
I don't know what is best, or if there is another way to process the messages (there is probably a windows function that can launch the loop)
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
It is not just for your own benefit, COM requires you to create a message loop. COM needs it to handle apartment threaded COM servers, an expensive word for "components that don't support multi-threading". The vast majority of them don't.
It is best to create a window, it doesn't have to be visible. That gives you a HWND that you can use in your SendMessage() calls. The window procedure you write can process the messages. From there, it gets to be easy to create a minimal user interface, with Shell_NotifyIcon for example. Always nice when you can display a notification when something goes wrong. So much better then an event in a log that nobody ever looks at.
Yes, you can. Every thread can have one message loop and you don't need any windows to receive messages or send them (see PostThreadMessage).
There is nothing wrong with using this method if your application is event-driven.

Avoiding "(Not Responding)" label in windows while processing lots of data in one lump

I occasionally need to process a large amount of data from one package off the network, which takes sufficiently long that when the user tries to interact with the application windows adds the "(Not Responding)" string to the window title. I am aware this is because the processing is being done within a call to handle a message (some way up the stack) and therefore is blocking the message pump. I'm also aware the ideal way to deal with this is to process the data asynchronously in a separate thread so the pump can continue running, however this is a LARGE desktop application which is single threaded from top to toe and safely spinning this processing off is not feasible in our time frame.
So with that in mind, is there by any chance a way I can at least avoid the "not responding" moniker (which to most users reads as "has crashed") by telling windows my application is about to be busy before I begin the work? I believe there is something along these lines when responding to a request to close, one can keep asking windows for more time to avoid it proclaiming that your not "closing in a timely fashion"
I should add this is a C++ MFC application.
I don't think the Windows API can help you here.
Alternatively, how about showing a dialog box with a progress bar and make it run in a separate thread?
A text like "This operation may take half an hour" on the dialog box may be appropriate too.
Ok, firstly I upvoted Frederick's post because like it or not, the second thread is probably the best way to go.
However, if you really don't want to go down this road, you could manually pump the message queue within your apps inner loop. Something like this;
int Refresh()
{
MSG msg;
if (PeekMessage (&msg, NULL, 0, 0,PM_NOREMOVE))
if ((msg.message == WM_QUIT)
||(msg.message == WM_CLOSE)
||(msg.message == WM_DESTROY)
||(msg.message == WM_NCDESTROY)
||(msg.message == WM_HSCROLL)
||(msg.message == WM_VSCROLL)
)
return(1);
if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(0);
}
This is actually a piece of code I used prior to rewriting something similar as a seperate thread. Basically I have a look at the queue, filter out unwanted messages, and post on the rest. It works to an extent, but caused some occasional nasty side effects, hence the rewrite.
You don't have to actually do anything with the messages from PeekMessage. Just call PeekMessage, you don't even have to remove anything from the queue or process it. As long as it is called every 5 seconds or so, it will cause windows to think the process is still responsive.
An alternative idea is to have a separate process/thread that will appear in the notification tray and inform the user that the process is busy waiting for an internal operation to complete. You'll see these in the later versions of Visual Studio, SQL Server Management Studio, etc.
Win32 has a method for this in user32.dll.
DisableProcessWindowsGhosting()
Disables the window ghosting feature for the calling GUI process. Window ghosting is a Windows Manager feature that lets the user minimize, move, or close the main window of an application that is not responding.
In addition to the above documented behavior, I also verified here (in a C# application) that this Win32 call also prevents the Not Responding label from appearing on the window as desired.
I found this via the C# answer to similar question here: https://stackoverflow.com/a/15380821/29152.
If you fork off a thread you're most likely worried about some other user action happening which may depend on the result of the long running operation (yeah, concurrency). So expanding on what Fredrick said, if you do spin off a new thread and put up a progress bar, you could lock the focus onto the progress bar to stop a user from interacting with the rest of the application. That should be enough to implement a really simple second thread without really having to worry about concurrency because you're essentially locking out the rest of the app by disabling user interation.
You'll need to interleave the processing with message handling somehow. If threads are out of the question, you might want to look at splitting the processing into multiple phases. One way to do this is to do some processing when you first receive the packet, then post a message to the application saying "continue processing here". When the application receives the "continue processing here" message, it will do some more processing, and either send another "continue processing here" message or finish up.
There are a couple of considerations though:
You need to make sure that the state of the application is consistent every time you post a message to yourself and defer to the message loop, as other message handling might happen in the mean-time. This can be done e.g. by only changing the state in the final processing phase.
Another packet might arrive while you are still processing the first packet. If changing the order of processing would be bad for the application, you could handle this by e.g. posting a "remind me to process this packet later" message when this happens.
I don't know whether this would be feasible within the design of your application, but it would be one way to solve the problem.
If you are unwilling to spawn a worker thread, but you can break the long-running task down into smaller parts, you can do the processing in MFC's CWinApp::OnIdle. This function gets called from within the message pump loop whenever there are no Windows messages waiting. As long as the work you do in each OnIdle call is sufficiently short, you keep your app responsive.
Assuming that it is the processing of the data that is taking up all the time and not the receiving (and you're serious about avoiding a thread - which is fine IMOHO) of the data you could:
In the function that you are currently handling the message, create a modal dialog that shows a "please wait" message (or make it hidden, small, whatever...). Copy (or send a pointer, etc...) the data you're processing to a member variable of that dialog.
In the modal dialog post a user-defined message to yourself to process the data.
In the dialog's message handler, handle one "unit" of work. Keep track what the next "unit" of work is. Post the same message again.
Repeat this post-message "loop" until done. Close your dialog.
The nature of the modal dialog will keep you're application "responsive", with minimal interruption or change to how the application worked previously. Reentrancy can be a problem with modal loops, especially if any of this is involved with a WM_PAINT message. (anyone ever assert inside painting code? good times, good times...)
The dialog could even have a cancel button if you'd like.
I encountered the exact same problem.
Since I dont consider the other answers appealing/straightforward I decided to post this.
Short description and some context:
I am saving data from a grid into a database, and this process can take a while. So I changed the saving method to an asynchronous method and had the same problem.
Then I came up with a simple solution:
//__ENABLE OR DISABLE MAIN DIALOG
void CMFCApplication1Dlg::enableMainDlg(bool enable)
{
this->EnableWindow(enable);
}
When starting the asynchronous method, I disable the main dialog.
This prevents the user from interacting with the main dialog (like starting another saving process which could result in thousands of SQL error messages if I wouldn't check if the saving process is already running...)
When the saving process is finished, I re-enable the main dialog.
Works like a charm, I hope this helps
One way to overcome your application from becoming unresponsive you need to tell the application to process messages from windows. When you are in your loop you can call
Application->ProcessMessages();
I had a similar issue with a win32 app that was waiting on a response from webservice using cpprest (Casablanca) api. My solution was to create a event and thread that does nothing but wait for the cpprest api and then release the thread once it recieves the signal:
DWORD WINAPI WaitForCasablanca(LPVOID n)
{
// Get the handler to the event for which we need to wait in
// this thread.
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "MyEvent");
if (!hEvent) { return -1; }
// Loop through and wait for an event to occur
// Wait for the Event
WaitForSingleObject(hEvent, INFINITE);
// No need to Reset the event as its become non signaled as soon as
// some thread catches the event.
CloseHandle(hEvent);
return 0;}
BOOL WINAPI DlgProc(HWND hDlg, UINT message, WPARAM,wParam, LPARAM lParam) ...
HANDLE hEvent = CreateEvent(NULL, false, false, "MyEvent");//create an event that will wait for casablanca ro authenticate
if (!hEvent) return -1;
// Create a Thread Which will wait for the events to occur
DWORD Id;
HANDLE hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitForCasablanca, 0, 0, &Id);
if (!hThrd) { CloseHandle(hEvent); return -1; }
makeCasablancaRequest(...);
SetEvent(hEvent); //casablanca has finished signal the event to terminate
WaitForSingleObject(hThrd, INFINITE); //wait for thread to die
CloseHandle(hThrd);
CloseHandle(hEvent);
...}
That got rid of the "program not responding" message for me. I believe the problem is the code that is getting the data is running in a thread too- only the main program doesn't know this- so as far as the system is concerned the main program is idling. You need an event and a thread that waits for the event to tell the system the program is waiting on data. I got the code from this tutorial: How to use WIN32 Event Kernel Object