在C ++ / Win32中检测进程崩溃

时间:2018-08-02 16:20:13

标签: c++ windows winapi process win32-process

我正在开发包含2个程序的软件:Qt Main exe + OpenGL Game exe

我们一开始总是使用Qt Main exe。当我们点击“开始游戏”按钮时,我们执行OpenGL Game exe。没问题。

问题是,有时我们在OpenGL Game exe中发生崩溃,我们希望将包含日志的崩溃报告发送到我们的崩溃报告邮件中。

我在Win32 API中找到了一个函数(registerwaitforsingleobject),但我不知道该进程是否崩溃: https://docs.microsoft.com/en-gb/windows/desktop/api/winbase/nf-winbase-registerwaitforsingleobject

我只想使用win32 api(从WinXP-WinVist到Win10)

预先感谢

4 个答案:

答案 0 :(得分:0)

使用现成的解决方案,例如CrashRpt http://crashrpt.sourceforge.net/。当抛出异常时,它将安装适当的处理程序并报告/提交所需的内容。

答案 1 :(得分:0)

您可以使用Interprocess Communications with a pipe

每隔一段时间(例如1秒)发送一条消息。如果没有响应,则几乎可以确定其他程序已崩溃。

另一种不太优雅的方法是测试日志文件,该日志文件每隔x秒修改一次,其值表示“我还活着,没有崩溃”。

答案 2 :(得分:0)

假设您关心的程序具有正常的Windows事件循环,或多或少的标准方式来检查其是否以合理及时的方式处理消息是使用SendMessageTimeout向其发送WM_NULL消息。

该程序不会响应WM_NULL,但是如果消息在消息队列中停留的时间过长(您选择“太长”的含义),SendMessageTimeout将会超时当您拨打电话时)。因此,您发送了它,然后检查它是否超时。

但是请注意:这仅适用于处理Windows消息的程序。如果没有消息循环,它将始终超时。哦,程序是多线程的,一个线程可能会“崩溃”(例如,进入无限循环),而其他线程则继续正常运行,因此,甚至很难定义“崩溃”的含义。

答案 3 :(得分:0)

我找到了解决问题的方法:我使用了Win32 API(https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess)中的GetExitCodeProcess函数。

这是示例代码:

int main(int argc, char** arv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

const char * prgm = "CrashedProcess.exe";
LPSTR prgmLpstr = const_cast<LPSTR>(prgm);

// Start the child process. 
if (!CreateProcess(NULL,   // No module name (use command line)
    prgmLpstr,        // Command line
    NULL,           // Process handle not inheritable
    NULL,           // Thread handle not inheritable
    FALSE,          // Set handle inheritance to FALSE
    0,              // No creation flags
    NULL,           // Use parent's environment block
    NULL,           // Use parent's starting directory 
    &si,            // Pointer to STARTUPINFO structure
    &pi)           // Pointer to PROCESS_INFORMATION structure
    )
{
    printf("CreateProcess failed (%d).\n", GetLastError());
    return -1;
}

// Wait until child process exits.
auto ret = WaitForSingleObject(pi.hProcess, INFINITE);
printf("WaitForSingleObject ret = %x\n", ret);
if (ret == WAIT_OBJECT_0)
{
    printf("WaitForSingleObject ret ret == WAIT_OBJECT_0\n");
}
BOOL b = FALSE;
DWORD n = 0;
b = GetExitCodeProcess(pi.hProcess, &n);
if (n == 0xC0000005)
{
    printf("Process Crashed !!!\n");
}

// Close process and thread handles. 
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
printf("WaitForSingleObject end\n");
return 0;
}

CrashedProcess.exe源代码:

int main()
{
   int * ptr = nullptr;
   *ptr = 123;
   return 0;
}