windows MessageBox 超时或从另一个线程关闭 MessageBox
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3091300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MessageBox with timeout OR Closing a MessageBox from another thread
提问by Patrick
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.
如果我的应用程序崩溃,我会使用 ExceptionFilter 来捕获崩溃,执行一些最终操作,然后向用户显示应用程序崩溃的消息框。
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, ...
因为应用程序已经崩溃,所以我不能(或我不敢)做太多事情,因为如果我做的太多,执行的代码可能会访问损坏的内存并再次崩溃。我目前不能做(或者我不敢做)的一些事情是关闭网络连接、Oracle 数据库会话、...
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:
问题是,如果应用程序崩溃,并且用户出去吃午饭而 MessageBox 处于打开状态,则其他用户可能会因为打开的数据库会话而被阻止。因此我想要:
- 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).
- 要么是带有超时的 MessageBox。问题是你不能用标准的 MessageBox Win32 API 函数做到这一点,我不想为它做一个特定的对话框(因为我想在崩溃后最小化执行的逻辑)
- 或者从另一个线程关闭 MessageBox 的可能性(另一个线程可以提供超时逻辑)。
Did I overlook something in the Win32 API and is there a possibility to have a MessageBox with a time-out?
我是否忽略了 Win32 API 中的某些内容,是否有可能使 MessageBox 超时?
Or what is the correct way to close an open MessageBox from another thread (how to get the MessageBox handle, how to close it, ...)?
或者从另一个线程关闭打开的 MessageBox 的正确方法是什么(如何获取 MessageBox 句柄,如何关闭它,......)?
采纳答案by Patrick
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).
我注意到如果主线程只是简单地退出应用程序而另一个线程仍然打开 ::MessageBox,则 MessageBox 正在被名为 CSRSS 的进程采用。这解决了我的问题,因为这仅需要主线程中的事件超时(WaitForSingleObject with timeout)。
However, this raised another question: https://stackoverflow.com/questions/3091915/explanation-why-messagebox-of-exited-application-is-adopted-by-winsrv.
然而,这引发了另一个问题:https: //stackoverflow.com/questions/3091915/explanation-why-messagebox-of-exited-application-is-adopted-by-winsrv。
回答by Alex K.
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()
)
虽然我同意生成一个新进程来显示即发即弃对话框可能是最好的,但 FWIW 实际上有一个从 XP 及更高版本上的 user32 导出的可超时消息框函数;MessageBoxTimeout
(如被使用的东西WShell.Popup()
)
回答by Timbo
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.
如果你真的想要它,我认为最简单的解决方案是产生一个显示消息的新进程。它可以随心所欲地运行,并且不会干扰您崩溃的程序。
回答by Simon
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;
}
回答by MSalters
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.
Win32 MessageBox 实际上是一个对话框,带有一个对话框消息泵。因此,您可以依赖标准的 Win32 计时器消息 (WM_TIMER)。将一个发送到您自己的窗口,当您收到它时,通过向WM_COMMAND/BN_CLICKED
ID_OK 按钮发送一条消息来关闭 MessageBox 。
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.
消息框,因为它是一个对话框,将是类“#32770”。因为它是您将打开的唯一对话框,所以很容易在您的子窗口中找到。
回答by glutorange
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.
一旦应用程序再次启动,您就可以通知您的用户(基于本地文件信息)应用程序在上次执行期间崩溃了。
回答by Pavel Radzivilovsky
This does not justify a thread.
这并不能证明线程是合理的。
The best solution would be to use a modal dialog box that registers a timer for auto-close.
最好的解决方案是使用一个模式对话框来注册一个自动关闭的计时器。
回答by Bob Moore
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.
我会从一个包装应用程序内部运行您的原始代码,该应用程序执行 CreateProcess,然后在进程句柄上运行 MsgWaitForMultipleObjects(大多数进程启动代码示例使用 WaitForSingleObject,但您需要防止消息传递死锁情况)。然后,您的监视进程可以检测到生成的进程的失败,弹出自己的超时对话框,并在用户响应或超时时退出。
I think that's the cleanest solution which prevents your unstable program having to execute any code.
我认为这是最干净的解决方案,可以防止您的不稳定程序必须执行任何代码。