نأسف لعدم كتابة أي شيء مثير للاهتمام هذا الشهر حتى الآن ، لقد كان شهرًا محمومًا للغاية.

رأيت اليوم سؤالاً على Stack Overflow بخصوص التصحيح. كان المستخدم يحاول السماح لـ Visual Studio بالعمل في وضع التصحيح مع تطبيقه لمعرفة متى ولماذا يتعطل.

هذا ليس حلاً لأن هناك وظائف مطبقة لهذه المواقف في Windows API. ببساطة ، يمكنك جعل برنامجك يكتب تفريغًا صغيرًا عند التعطل ، ثم يمكنك فتحه داخل Visual Studio (أو أي مصحح أخطاء تريده) ومعرفة مكان تعطله بالضبط.

المثال أدناه جاهز للاستخدام مع أي .exe أو .dll على 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{
10    LPTOP_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}

لاستخدامه ، اتصل بما يلي في بداية + نهاية نقطة دخول البرنامج. على سبيل المثال .dll:

 1#include "MiniDump.hpp"
 2
 3BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
 4{
 5   switch ( ul_reason_for_call )
 6   {
 7      case DLL_PROCESS_ATTACHED:
 8      MecanikUtils::MiniDump::Init();
 9      break;
10      
11      case DLL_PROCESS_DETACH:
12      MecanikUtils::MiniDump::Clean();
13      break;
14   }
15   return TRUE;
16}

لا تتردد في إجراء تغييرات على SetErrorMode إذا كنت بحاجة إلى ذلك.

** ملاحظة: ** احتفظ بالنسخة الأصلية .pdb للمترجم. exe / .dll إذا كنت تريد فتح التفريغ الصغير. وإلا فلن يكون لديك أي معلومات سهلة القراءة.

حتى المرة القادمة! 😉