Created
August 6, 2024 21:23
-
-
Save adamjs/8f20df17e1b8c3945863eca9c91a97ce to your computer and use it in GitHub Desktop.
Utility code to log crashes to .dmp files on Windows for remote debugging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <dbghelp.h> | |
#include <iostream> | |
#include <strsafe.h> | |
// Link with the DbgHelp.lib | |
#pragma comment(lib, "dbghelp.lib") | |
// Function to create the dump file | |
void CreateDump(EXCEPTION_POINTERS* pExceptionPointers, TCHAR* szFileName) | |
{ | |
// Define the dump file path | |
TCHAR szPath[MAX_PATH]; | |
SYSTEMTIME st; | |
GetSystemTime(&st); | |
GetTempPath(MAX_PATH, szPath); | |
StringCchPrintf(szFileName, MAX_PATH, TEXT("%s%s_%04d%02d%02d_%02d%02d%02d.dmp"), szPath, TEXT("MyAppCrashDump"), | |
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); | |
// Create the dump file | |
HANDLE hDumpFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
if (hDumpFile != INVALID_HANDLE_VALUE) | |
{ | |
MINIDUMP_EXCEPTION_INFORMATION dumpInfo; | |
dumpInfo.ThreadId = GetCurrentThreadId(); | |
dumpInfo.ExceptionPointers = pExceptionPointers; | |
dumpInfo.ClientPointers = TRUE; | |
// Write the dump file | |
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &dumpInfo, NULL, NULL); | |
CloseHandle(hDumpFile); | |
} | |
} | |
// Custom unhandled exception filter | |
LONG WINAPI CustomUnhandledExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) | |
{ | |
TCHAR szFileName[MAX_PATH]; | |
CreateDump(pExceptionPointers, szFileName); | |
// Copy file path to clipboard | |
if (OpenClipboard(NULL)) | |
{ | |
EmptyClipboard(); | |
size_t size = (lstrlen(szFileName) + 1) * sizeof(TCHAR); | |
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, size); | |
if (hMem) | |
{ | |
memcpy(GlobalLock(hMem), szFileName, size); | |
GlobalUnlock(hMem); | |
SetClipboardData(CF_UNICODETEXT, hMem); | |
} | |
CloseClipboard(); | |
} | |
// Show a message box with the dump file location | |
TCHAR szMessage[MAX_PATH + 50]; | |
StringCchPrintf(szMessage, MAX_PATH + 50, TEXT("The application has crashed.\nA dump file has been created and the path has been copied to the clipboard:\n%s"), szFileName); | |
MessageBox(NULL, szMessage, TEXT("Application Crash"), MB_OK | MB_ICONERROR); | |
return EXCEPTION_EXECUTE_HANDLER; | |
} | |
// Function to cause a crash (access violation) | |
void CauseCrash() | |
{ | |
int* p = nullptr; | |
*p = 0; // CRASH!! | |
} | |
int main() | |
{ | |
// Only install our custom unhandled exception filter if the debugger isn't attached. | |
if (!IsDebuggerPresent()) | |
{ | |
// Set the custom unhandled exception filter | |
SetUnhandledExceptionFilter(CustomUnhandledExceptionFilter); | |
} | |
std::cout << "This app will crash to test crash dump logging." << std::endl; | |
// Cause a crash | |
CauseCrash(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment