带有超时的消息框或在另一个线程中关闭消息框

7
如果我的应用程序崩溃了,我会使用ExceptionFilter来捕获崩溃,执行一些最终操作,然后向用户显示一个消息框,告诉他们应用程序已经崩溃。
由于应用程序已经崩溃,我无法做太多事情,因为如果我做太多,执行的代码可能会访问损坏的内存并再次崩溃。我目前无法做的一些事情是关闭网络连接、Oracle数据库会话等。
问题在于,如果应用程序崩溃,而用户正在吃午饭时MessageBox打开,其他用户可能会被阻塞,因为数据库会话仍然处于打开状态。因此,我需要:
要么是带有超时的MessageBox。问题是您无法使用标准MessageBox Win32 API函数完成此操作,我也不想为其制作特定对话框(因为我想尽量减少崩溃后执行的逻辑)。
要么是从另一个线程关闭MessageBox的可能性(另一个线程可以提供超时逻辑)。
我是否忽略了Win32 API中的某些内容,有没有可能拥有带有超时的MessageBox?
或者从另一个线程正确关闭打开的MessageBox的方法是什么(如何获取MessageBox句柄,如何关闭它等)?
8个回答

6

虽然我同意生成一个新的进程来显示一个即时对话框可能是最好的选择,但值得一提的是,在XP及以上版本的user32中实际上导出了一个可超时的消息框函数;MessageBoxTimeout(如WShell.Popup()所使用)。


5

快速复制/粘贴解决方案:

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;
}

3

首先,你应该问自己为什么需要一个消息框。如果在没有人坐在电脑前时看不到消息框是可以接受的,那么当用户的程序消失时,为什么不能接受他不看到消息呢?

如果你真的想要它,我认为最简单的解决方案是生成一个显示消息的新进程。它可以运行任意长时间,并且不会干扰你正在崩溃的程序。


2

1

这并不需要开启一个线程。

最好的解决方案是使用模态对话框,为其注册一个自动关闭的计时器。


我想提出相同的建议:使用DialogBox创建一个新的对话框, 在WM_INITDIALOG中创建一个带有SetTimer的计时器,并在WM_TIMER中关闭对话框。 - Oleg

1

那么只记录事件到本地文件中(并记录内存转储或其他可能需要进行后期调试的信息)怎么样?

您可以关闭应用程序、关闭网络连接并执行清理工作。

一旦应用程序再次启动,您可以根据本地文件信息通知用户上次执行时应用程序已崩溃。


1

Win32的MessageBox实际上是一个对话框,具有对话框消息泵。因此,您可以依靠标准的Win32计时器消息(WM_TIMER)。将其发送到您自己的窗口,当您收到它时,通过向ID_OK按钮发送WM_COMMAND/BN_CLICKED消息来关闭MessageBox。

由于MessageBox是一个对话框,所以它的类别为“#32770”。由于它是您唯一打开的对话框,因此很容易在子窗口中找到它。


0

我建议你在一个包装应用程序中运行原始代码,该应用程序使用CreateProcess执行操作,然后使用过程句柄(MsgWaitForMultipleObjects)进行等待(大多数进程启动代码示例使用 WaitForSingleObject,但需要防止消息死锁情况)。此时你的监视进程可以检测到衍生进程的失败、弹出自己的超时对话框,并根据用户响应或超时退出。

我认为这是最干净的解决方案,可以避免不稳定程序执行任何代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接