Entschuldigung, dass ich diesen Monat bisher nichts Interessantes geschrieben habe, es war ein sehr hektischer Monat.
Heute habe ich eine Frage auf Stack Overflow zum Thema Debugging gesehen. Der Benutzer versuchte, Visual Studio im Debug-Modus mit seiner Anwendung laufen zu lassen, um zu sehen, wann und warum sie abstürzt.
Das ist keine Lösung, denn es gibt Funktionen für diese Situationen in der Windows API. Einfacher gesagt: Sie können Ihre Software so einrichten, dass sie bei einem Absturz einen Mini Dump schreibt, den Sie dann einfach in Visual Studio (oder einem anderen Debugger Ihrer Wahl) öffnen können, um genau zu sehen, wo der Absturz passiert ist.
Das folgende Beispiel ist sofort einsetzbar für jede .exe oder .dll unter Windows:
1#pragma once
2
3#include <Windows.h>
4#include <Dbghelp.h>
5#pragma comment (lib, "Dbghelp.lib")
6
7// Because... why not ?!
8namespace MecanikUtils
9{
10LPTOP_LEVEL_EXCEPTION_FILTER PreviousExceptionFilter = 0;
11
12 LONG WINAPI DumpExceptionFilter(EXCEPTION_POINTERS* info)
13 {
14 wchar_t DumpPath[MAX_PATH] = { 0 };
15
16 SYSTEMTIME SystemTime;
17 GetLocalTime(&SystemTime);
18
19 WCHAR szExeFileName[100] = { 0 };
20 GetModuleFileNameW(NULL, szExeFileName, 99);
21
22 wsprintfW(DumpPath, L"Crash_%s_%d-%d-%d_%dh%dm%ds.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);
23
24 HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
25
26 if (file != INVALID_HANDLE_VALUE)
27 {
28 MINIDUMP_EXCEPTION_INFORMATION mdei;
29
30 mdei.ThreadId = (DWORD)GetCurrentThreadId();
31
32 mdei.ExceptionPointers = info;
33
34 mdei.ClientPointers = 0;
35
36 if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD)GetCurrentProcessId(), file, (MINIDUMP_TYPE)(MiniDumpScanMemory + MiniDumpWithIndirectlyReferencedMemory), &mdei, 0, 0) != 0)
37 {
38 CloseHandle(file);
39 return EXCEPTION_EXECUTE_HANDLER;
40 }
41 }
42
43 CloseHandle(file);
44
45 return EXCEPTION_CONTINUE_SEARCH;
46 }
47
48 class MiniDump
49 {
50 public:
51
52 /// <summary>
53 /// Add Unhandled Exception Filter
54 /// </summary>
55 inline static void Init()
56 {
57 // Change if required
58 SetErrorMode(SEM_FAILCRITICALERRORS);
59
60 PreviousExceptionFilter = SetUnhandledExceptionFilter(DumpExceptionFilter);
61 }
62
63 /// <summary>
64 /// Remove Unhandled Exception Filter
65 /// </summary>
66 inline static void Clean()
67 {
68 SetUnhandledExceptionFilter(PreviousExceptionFilter);
69 }
70 };
71
72}Um es zu verwenden, rufen Sie einfach Folgendes am Anfang und Ende des Einstiegspunkts Ihrer Software auf. Zum Beispiel eine .dll:
1#include "MiniDump.hpp"
2
3BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
4{
5switch ( ul_reason_for_call )
6{
7case DLL_PROCESS_ATTACHED:
8MecanikUtils::MiniDump::Init();
9break;
10
11 case DLL_PROCESS_DETACH:
12 MecanikUtils::MiniDump::Clean();
13 break;
14
15}
16return TRUE;
17}Fühlen Sie sich frei, Änderungen an SetErrorMode vorzunehmen, wenn nötig.
Hinweis: Behalten Sie die originale .pdb der kompilierten .exe/.dll, wenn Sie den Mini Dump öffnen möchten. Andernfalls haben Sie keine leicht lesbaren Informationen.
Bis zum nächsten Mal! 😉
Kommentare