比较详细的地址是:http://www.codeproject.com/debug/XCrashReportPt3.asp
不过作者考虑了没有vc等情况。
其实如果有vc使用ms 的 MiniDumpWriteDump 将会非常简单. 如下面100行左右搞定,理解、转换为unicode 编码都简单很多.只需要装入相应的头文件即可记录crash dump 文件。用vc打开dump 文件。按F5即可运行到crash地点
vc Release 工程必须设置:
链接器 ->调试-> 生成调试信息 是(/DEBUG)
链接器->优化->引用->消除未引用数据(/OPT:REF)
头文件 minidump.h
#pragma once
#include <windows.h>
#include <tchar.h>
#if _MSC_VER < 1300
#define DECLSPEC_DEPRECATED
// VC6: change this path to your Platform SDK headers
#include "c://dev7//vs//devtools//common//win32sdk//include//dbghelp.h" // must be XP version of file
#else
// VC7: ships with updated headers
#include "dbghelp.h"
#endif
// based on dbghelp.h
class MiniDumper
{
typedef BOOL (WINAPI* MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
private:
static LPCTSTR m_szAppName;
static LONG WINAPI TopLevelFilter(struct _EXCEPTION_POINTERS *pExceptionInfo);
public:
MiniDumper(LPCTSTR szAppName);
~MiniDumper();
};
//源文件 minidump.cpp
#include "minidump.h"
#include <assert.h>
#include <stdio.h>
#include <direct.h>
LPCTSTR MiniDumper::m_szAppName;
#ifndef _DEBUG
MiniDumper dumper(_T("xyj2007"));
#endif
MiniDumper::MiniDumper(LPCTSTR szAppName)
{
// if this assert fires then you have two instances of MiniDumper which is not allowed
assert( m_szAppName==NULL ); //确认只创建一个 minidumper
m_szAppName =_tcsdup(szAppName);
::SetUnhandledExceptionFilter(TopLevelFilter);
}
MiniDumper::~MiniDumper()
{
if(m_szAppName)
{
free( (void *) m_szAppName);
m_szAppName = NULL;
}
}
LONG MiniDumper::TopLevelFilter( struct _EXCEPTION_POINTERS *pExceptionInfo )
{
LONG retval = EXCEPTION_CONTINUE_SEARCH;
HWND hParent = NULL; // find a better value for your app
// firstly see if dbghelp.dll is around and has the function we need
// look next to the EXE first, as the one in System32 might be old
// (e.g. Windows 2000)
HMODULE hDll = NULL;
TCHAR szDbgHelpPath[_MAX_PATH];
if (GetModuleFileName( NULL, szDbgHelpPath, _MAX_PATH ))
{
TCHAR *pSlash = _tcsrchr( szDbgHelpPath, _T('//') );
if (pSlash)
{
_tcscpy(pSlash+1, _T("DBGHELP.DLL"));
hDll = ::LoadLibrary( szDbgHelpPath );
}
}
if (hDll==NULL)
{
// load any version we can
hDll = ::LoadLibrary(_T("DBGHELP.DLL"));
}
LPCTSTR szResult = NULL;
if (hDll)
{
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll,"MiniDumpWriteDump");
if (pDump)
{
TCHAR szDumpPath[_MAX_PATH];
TCHAR szScratch [_MAX_PATH];
// work out a good place for the dump file
_tgetcwd(szDumpPath,_MAX_PATH);
_tcscat( szDumpPath, _T("//"));
_tcscat( szDumpPath, m_szAppName );
_tcscat( szDumpPath, _T(".dmp"));
// ask the user if they want to save a dump file
if (::MessageBox(NULL,_T("程序发生意外,是否保存一个文件用于诊断?"),m_szAppName,MB_YESNO)==IDYES)
{
// create the file
HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile!=INVALID_HANDLE_VALUE)
{
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
// write the dump
BOOL bOK = pDump( GetCurrentProcess(),GetCurrentProcessId(),hFile,MiniDumpNormal,&ExInfo,NULL,NULL);
if (bOK)
{
_stprintf( szScratch, _T("保存文件到:'%s'"), szDumpPath );
szResult = szScratch;
retval = EXCEPTION_EXECUTE_HANDLER;
}
else
{
_stprintf( szScratch, _T("保存文件到 '%s'失败,(错误号: %d)"), szDumpPath, GetLastError() );
szResult = szScratch;
}
::CloseHandle(hFile);
}
else
{
_stprintf( szScratch, _T("在'%s'创建 dump 文件失败,(错误号 %d)"), szDumpPath, GetLastError() );
szResult = szScratch;
}
}
}
else
{
szResult = _T("dbghelp.dll 文件太旧,不能支持MiniDumpWriteDump函数");
}
}
else
{
szResult = _T("dbghelp.dll 文件不存在");
}
if (szResult)
{
::MessageBox( NULL, szResult, m_szAppName, MB_OK );
}
return retval;
}