3

我发现了许多关于如何在需要时手动创建故障转储的帖子,但我想做的是确保在受监控的应用程序崩溃时生成故障转储。

TechNet PROCDUMP 工具可以完美地做到这一点。我想知道的是如何在我自己的管理程序中编写一些代码来做同样的事情,这样我就只在发生异常时创建一个转储文件。

我的程序是一个服务应用程序,它知道我希望监控的程序的进程 ID。

为了澄清起见,我想模仿这个对 PROCDUMP 的调用会做什么:

procdump -e someprocess.exe -w

从理论上讲,Windows 应该能够使用 DrWatson 为我完成这项工作。我遇到的问题是我有大约 200 个正在运行的客户系统声称我们的应用程序随机崩溃。Watson 博士似乎并没有确认我们的应用程序正在崩溃这一事实,所以我决定我宁愿让崩溃转储生成由我们自己的软件控制。

我已经设法让我自己的应用程序使用 __try/except 和 MiniDumpWriteDump() 和 MiniDumpWithFullMemory 类型创建自己的转储。但是我不能用 WinDbg 查看局部变量等,所以我猜这是因为它有是从应用程序本身内部触发的.. 所以.. 我想要一个监控/管理类型的应用程序来完成这项工作的另一个原因。

至少..一个应用程序如何对另一个应用程序崩溃做出反应?您是否必须安装某种调试钩子或假装管理程序实际上是自定义调试器?

干杯

4

1 回答 1

3

好的,我自己想通了。我已经编写了自己的“调试器”,它可以捕获在我的“调试器”附加到的程序中生成的异常。现在我只需要弄清楚如何编写该外部进程的小型转储。棘手的部分似乎是我必须提供一个 EXCEPTION_POINTERS 数组。这是我现在需要弄清楚的唯一一点。

这是一个示例代码片段。我希望它在未来对其他人有所帮助:

void WriteCrashDump( EXCEPTION_DEBUG_INFO *pExceptionInfo )
{
  CONTEXT c;

  memset( &c, 0, sizeof( c ) );

  GetThreadContext( hThread, &c );

  EXCEPTION_POINTERS ep;

  ep.ContextRecord   = &c;
  ep.ExceptionRecord = &pExceptionInfo->ExceptionRecord;

  MINIDUMP_EXCEPTION_INFORMATION minidump_exception;

  minidump_exception.ThreadId          = dwThreadId;
  minidump_exception.ExceptionPointers = &ep;
  minidump_exception.ClientPointers    = true;

  HANDLE hFile = CreateFile( "dump.dmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );

  if( hFile ) 
  {
    BOOL  fSuccess;

    fSuccess = MiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpWithFullMemory, &minidump_exception, NULL, NULL );

    if( ! fSuccess )
      printf( "MiniDumpWriteDump -FAILED\n" );

    CloseHandle( hFile );
  } 
}

void DebugLoop( void )
{
  DEBUG_EVENT de;

  while( 1 )
  {
    WaitForDebugEvent( &de, INFINITE ); 

    switch( de.dwDebugEventCode )
    {
      case CREATE_PROCESS_DEBUG_EVENT:
        hProcess = de.u.CreateProcessInfo.hProcess;
        break;

      case EXCEPTION_DEBUG_EVENT: 
        printf( "EXCEPTION_DEBUG_EVENT\n" ); 

        // PDS: Not interested in the fact that I have attached to it and caused a breakpoint..
        if( de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT )
          break;

        dwProcessId = de.dwProcessId;
        dwThreadId  = de.dwThreadId;

        WriteCrashDump( &de.u.Exception );
        return;

      default:
        break;
    }

    ContinueDebugEvent( de.dwProcessId, de.dwThreadId, DBG_CONTINUE );
  }
}
于 2011-09-16T01:00:36.347 回答