让Windows下的应用程序在崩溃的时候写dump文件的代码

时间:2021-08-29 19:51:44
#pragma once
#include "shared/util.h"
#include <DbgHelp.h>
#include "util/user.h"

BOOL CALLBACK MyMiniDumpCallback(PVOID, const PMINIDUMP_CALLBACK_INPUT input, PMINIDUMP_CALLBACK_OUTPUT output)
{
	if(input == NULL || output == NULL)
		return FALSE;

	BOOL ret = FALSE;
	switch(input->CallbackType)
	{
	case IncludeModuleCallback:
	case IncludeThreadCallback:
	case ThreadCallback:
	case ThreadExCallback:
		ret = TRUE;
		break;
	case ModuleCallback:
		{
			if( !(output->ModuleWriteFlags & ModuleReferencedByMemory) )
			{
				output->ModuleWriteFlags &= ~ModuleWriteModule;
			}
			ret = TRUE;
		}
		break;
	default:
		break;
	}

	return ret;
}

void WriteDump(EXCEPTION_POINTERS* exp, const std::wstring &path)
{
	HANDLE h = ::CreateFile(path.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, 
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	MINIDUMP_EXCEPTION_INFORMATION info;
	info.ThreadId = ::GetCurrentThreadId();
	info.ExceptionPointers = exp;
	info.ClientPointers = NULL;

	MINIDUMP_CALLBACK_INFORMATION mci; 
	mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback; 
	mci.CallbackParam = 0; 

	MINIDUMP_TYPE mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory); 

	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), h, mdt, &info, NULL, &mci);
	::CloseHandle(h);
}

LONG WINAPI MyUnhandledExceptionFilter(EXCEPTION_POINTERS* exp)
{
	nbase::Time::TimeStruct qt = nbase::Time::Now().ToTimeStruct(true);
	std::wstring file = nbase::StringPrintf(L"%04d%02d%02d_%02d%02d%02d.dmp", 
		qt.year_, qt.month_, qt.day_of_month_, qt.hour_, qt.minute_, qt.second_);
	std::wstring dir = QPath::GetNimAppDataDir();
	dir.append(file);

	WriteDump(exp, dir);

	std::wstring cmd = nbase::StringPrintf(L" /%s %s ", kCmdAppCrash.c_str(), dir.c_str());
	QCommand::RestartApp(cmd);

	return EXCEPTION_EXECUTE_HANDLER;
}

::SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);

详细原理见博客中的软件崩溃的callback和writedump文章


同时link的时候需要link Dbghelp.lib这个lib文件