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!
Related
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.
I made a thread to set some text on EditBox on Lobby Dialog. Below is my code.
And MainLobby is the Dialog Class. This project is "Dialog Based MFC Project".
MainLobby Lobby;
_beginthreadex(NULL, 0, ReceiveMessage, (void *)Lobby.GetSafeHwnd(), 0, NULL);
Lobby.DoModal();
But it doesn't work. Where is wrong? I thought hard but I couldn't find the answer.
I tried not Lobby.GetSafeHwnd() but Lobby.m_hwnd
unsigned WINAPI ReceiveMessage(void *arg)
{
HWND hDlg = (HWND)arg;
char msg[BUF_SIZE];
int msgLen;
while( (msgLen = recv(CClientApp::hSocket, msg, BUF_SIZE, 0)) != 0 )
{
SetDlgItemText(hDlg, IDC_LOBBY_CBOX, msg);
}
}
I am using MFC now. I will be glad a good idea.
The device context has to be updated.
Try:
UpdateData(true);
SetDlgItemText(hDlg, IDC_LOBBY_CBOX, msg);
UpdateData(false);
Or try it with a CString member variable for IDC LOBBY CBOX.
It is clear from your code that you are not using MFC properly. A Windows dialog based application does not require the programmer to explicitly create message handlers or receivers, that is what the MFC framework itself is doing for you. There is no reason to call beginthreadex before starting the dialog message loop as part of the DoModal method. When you invoke DoModal on any class descended From Dialog or DialogEX, the window is constructed, the member objects are constructed, and the message loop is started before the WM_INITDIALOG message is sent to the dialog for any other initialization before the dialog window is displayed. Once the window is displayed, the message loop is running, and text will display automatically in an edit control when you send it correctly. Normally one would declare a CEdit object with some name using the Class Wizard in visual studio then map the MFC object to the dialog object. Rather than type out all the details I will refer to this article: http://msdn.microsoft.com/en-us/library/6d1asasd.aspx
The dialog's HWND has not been initialized before DoModal is called. So your thread does not receive the proper HWND. The first place that you can access the correct HWND value is inside the dialog's OnInitDialog member function.
I see two problems in your code.
First you are calling Lobby.GetSafeHwnd before DoModal, so before the window is constructed. You should move the thread creation to the WM_INITDIALOG handler of MainLobby to create the thread there. Or you could create a modeless dialog.
Second you are using _beginthreadex in your MFC code. If you are starting a thread that uses MFC, then you need to start that thread with AfxBeginThread. If you only use CRT, then you use _beginthreadex. If you use neither, then use Windows CreateThread. The reason for this is that each layer (CRT, MFC) needs to do some housekeeping of thread specific information. This can only be done if you call the proper thread creation functions.
Third, you might consider using the MFC socket objects like CAsyncSocket. This object can send windows messages to your dialog if some data is available on the socket. This perfectly fits into your scenario with an MFC dialog that should handle socket data.
Another thing, but you already got that right: to access an MFC GUI object you need to be in the thread of that GUI object. So calling the Windows SetDlgItemText with the raw handle hDlg needs to be done, you cannot call an MFC function here.
BTW, are you sure your overall strategy is right? I don't see how you handle dialog life time, socket life time and how you put both together.
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.
If my application crashes, I use an ExceptionFilter to catch the crash, perform some final actions, then show a message box to the user that the application has crashed.
Because the application already crashed, there's not much I can (or I dare) to do, because if I do too much, the executed code might access corrupted memory and crash again.
Some of the things I currently can't do (or I don't dare to do) is to close network connections, Oracle database sessions, ...
Problem is that if an application crashes, and the user is out to lunch while the MessageBox is open, other users might be blocked, because of the open database session. Therefore I want:
Either a MessageBox with a time-out. Problem is that you can't do this with the standard MessageBox Win32 API function, and I don't want to make a specific dialog for it (because I want to minimize the executed logic after the crash)
Or the possibility to close the MessageBox from another thread (the other thread can provide the time-out logic).
Did I overlook something in the Win32 API and is there a possibility to have a MessageBox with a time-out?
Or what is the correct way to close an open MessageBox from another thread (how to get the MessageBox handle, how to close it, ...)?
While I agree that spawning a new process to display a fire-and-forget dialog is probably best, FWIW there is actually a timeoutable messagebox function exported from user32 on XP & above; MessageBoxTimeout (as used by things like WShell.Popup())
Quick copy/paste solution:
int DU_MessageBoxTimeout(HWND hWnd, const WCHAR* sText, const WCHAR* sCaption, UINT uType, DWORD dwMilliseconds)
{
// Displays a message box, and dismisses it after the specified timeout.
typedef int(__stdcall *MSGBOXWAPI)(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);
int iResult;
HMODULE hUser32 = LoadLibraryA("user32.dll");
if (hUser32)
{
auto MessageBoxTimeoutW = (MSGBOXWAPI)GetProcAddress(hUser32, "MessageBoxTimeoutW");
iResult = MessageBoxTimeoutW(hWnd, sText, sCaption, uType, 0, dwMilliseconds);
FreeLibrary(hUser32);
}
else
iResult = MessageBox(hWnd, sText, sCaption, uType); // oups, fallback to the standard function!
return iResult;
}
You should ask yourself, why you want a messagebox in the first place. When it is OK that the message box is not seen when noone is sitting in front of the computer, why isn't it OK that the user doesn't see a message when his program disappears?
If you really want it, I think the simplest solution is to spawn a new process displaying the message. It can run as long as it wants and does not interfer with your crashing program.
I noticed that if the main thread simply exits the application while the other thread still has the ::MessageBox open, that the MessageBox is being adopted by a process called CSRSS. This solves my problem, since this only requires a time-out on the Event in the main thread (WaitForSingleObject with timeout).
However, this raised another question: https://stackoverflow.com/questions/3091915/explanation-why-messagebox-of-exited-application-is-adopted-by-winsrv.
This does not justify a thread.
The best solution would be to use a modal dialog box that registers a timer for auto-close.
What about just logging the event to a local file (and record memory dumps or whatever information you might need for later debugging)?
You could close your application, close network connections and do your housekeeping stuff.
As soon as the application is started again, you can inform your user (based on local file information) that the application has crashed during last execution.
A Win32 MessageBox really is a dialog, with a dialog message pump. You can therefore rely on standard Win32 timer messages (WM_TIMER). Send one to your own window, and when you do get it, dismiss the MessageBox by sending a WM_COMMAND/BN_CLICKED message to the ID_OK button.
The messagebox, since it's a dialog, will be class "#32770". Since it's the only dialog box you will have open, it's easy to find amongst your child windows.
I would run your original code from inside a wrapper application that does a CreateProcess and then a MsgWaitForMultipleObjects on the process handle (most process launching code samples use WaitForSingleObject, but you need to guard against messaging deadlock scenarios). Your watching process can then detect the failure of the spawned process, pop up its own timed-out dialog, and exit on user response or timeout.
I think that's the cleanest solution which prevents your unstable program having to execute any code.
From the native Win32 API using C++ is there a way to determine whether the window associated with an HWND is still valid?
You could use the Win32 API IsWindow.
It is not recommended to use it though for 2 reasons:
Windows handles can be re-used once the window is destroyed, so you don't know if you have a handle to an entirely different window or not.
The state could change directly after this call and you will think it is valid, but it may really not be valid.
From MSDN (same link as above):
A thread should not use IsWindow for a
window that it did not create because
the window could be destroyed after
this function was called. Further,
because window handles are recycled
the handle could even point to a
different window.
What can be done?
Perhaps your problem can be re-architected so that you do not have the need to check for a valid handle. Maybe for example you can establish a pipe from the client to the server.
You could also create a windows hook to detect when certain messages occur, but this is probably overkill for most needs.
This question is old, but I needed this functionality myself and was a bit disappointed after reading about the caveats. However, after doing a bit more digging it seems that all is well. Unless you're dealing with 16bit programs, IsWindow appears to be the way to go. The problem of handle re-use appears to have been sufficiently addressed according to this:
http://blogs.msdn.com/b/oldnewthing/archive/2007/07/17/3903614.aspx
So, because of the upper 16bit reuse counter, it is highly unlikely that you'll run into a window reuse problem.
You can use IsWindow() or also try to send the window a WM_NULL message with SendMessage(hWnd, WM_NULL) and see if it is successful.
Also, it is true that the window could be destroyed at any time if it isn't under your control. As others have stated the handle could potentially belong to another window as the handles are reused. In reality I don't know how likely that is.
The only solution that I know of the to create a system wide hook that looks for messages indicating a window is destroyed (WM_CLOSE, WM_DESTROY). Then you would compare the message window handle to ones you are holding to see if any of the windows you care about are affected. See here for more information on system wide hooks.
Maybe a combination of IsWindow, FindWindow and GetWindowThreadProcessId will be more accurate
HWND windowHandle = FindWindow(NULL, TEXT("window_title"));
LPDWORD oldpid = 0;
GetWindowThreadProcessId(windowHandle, &oldpid);
//after some time
if (IsWindow(windowHandle))
{
LPDWORD newpid = 0;
GetWindowThreadProcessId(windowHandle, &newpid);
if (newpid == oldpid)
{
//the window is still running
}else
{
//the window exists but has changed
}
}
If the window procedure for the window in question is under your control (or if you can subclass it), then I would suggest registering a custom message that the window responds to with a non-zero result. Sending that message to any other window (or an invalid HWND) will result in 0.
Of course, that only tells you if the HWND refers to one of the windows that you control -- but perhaps given other answers above that might even be advantageous.
Use RegisterWindowMessage to register the message, using a sufficiently unique name.
if(IsWindow(FindWindow(NULL , TEXT("Example Window Name")))){
// do stuff
}
will check if the window exists and has the appropriate name