To create minidumps in a managed environment, use the features of the DbgHelp.dll library. Consider the use of its functionality on the example of the finished project on WinForms.
We write code that creates minidumps
First of all, note that minidumps should be created when an unhandled exception occurs. In order, for example, to generate such an exception, during the execution of the program, we will divide by zero when the user clicks a certain button:
')
private void button1_Click_1(object sender, EventArgs e) { int a = 3; int b = 0; int c = a / b; }
Now consider the mechanisms by which projects handle exceptions that are not processed by developer code. We are interested in two handlers:
AppDomain.CurrentDomain.UnhandledException Application.ThreadException
ThreadException typically handles unhandled exceptions associated with UI threads (such as those that may occur in WinForms events). All other unhandled exceptions cause the program to stop. However, before the final completion of its work, you can perform some of the actions we need: save the user data, or, as in our case, write to the hard disk minidump. To do this, use the UnhandledException handler.
In order to simplify the solution of the problem, let us make sure that all exceptions are handled by UnhandledException. To do this, before the Application.Run (new Form1) method in Main (), call the following method:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
From this point on, ThreadException does not interest us.
All actions for handling exceptions with DbgHelp are encapsulated into one DumpMaker class, which will have an important method for us with the following signature:
public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
This is the method we will register to handle UnhandledException:
AppDomain.CurrentDomain.UnhandledException += DumpMaker.CurrentDomain_UnhandledException;
Now the program will call our method before crashing.
DumpMaker Class Content
private static class MINIDUMP_TYPE { public const int MiniDumpNormal = 0x00000000; ... public const int MiniDumpWithCodeSegs = 0x00002000; }
MINIDUMP_TYPE contains all the types of minidumps we can create. Each type is associated with a specific constant. A complete list of constants can be found on the
website .
[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct MINIDUMP_EXCEPTION_INFORMATION { public uint ThreadId; public IntPtr ExceptionPointers; public int ClientPointers; }
MINIDUMP_EXCEPTION_INFORMATION - the structure that will store the information about the exception, due to which the program completed its work.
[DllImport("kernel32.dll")] static extern uint GetCurrentThreadId();
Returns the current process ID.
[DllImport("Dbghelp.dll")] static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, IntPtr hFile, int DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
The library method that directly performs the creation of a dump and its recording. It is called from the method.
private static void CreateMiniDump() { using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess()) { string FileName = string.Format(@"CRASH_DUMP_{0}_{1}.dmp", DateTime.Today.ToShortDateString(), DateTime.Now.Ticks); MINIDUMP_EXCEPTION_INFORMATION Mdinfo = new MINIDUMP_EXCEPTION_INFORMATION(); Mdinfo.ThreadId = GetCurrentThreadId(); Mdinfo.ExceptionPointers = Marshal.GetExceptionPointers(); Mdinfo.ClientPointers = 1; using (FileStream fs = new FileStream(FileName, FileMode.Create)) { { MiniDumpWriteDump(process.Handle,(uint)process.Id, fs.SafeFileHandle.DangerousGetHandle(), MINIDUMP_TYPE.MiniDumpNormal, ref Mdinfo, IntPtr.Zero, IntPtr.Zero); } } } }
The dump is written to a file with a unique name (FileName), which will be stored in the same directory as the exe file. Before calling MiniDumpWriteDump, we initialize the structure of the MINIDUMP_EXCEPTION_INFORMATION type.
Consider a list of MiniDumpWriteDump parameters.
hProcess - the process descriptor for which the information is generated
ProcessID - The process ID for which the information is generated.
hFile - file descriptor
DumpType - dump type (we will use MiniDumpNormal)
ExceptionParam - exception information
UserStreamParam - user-defined information. We will not include it in the dump and pass it to the IntPtr.Zero method.
CallbackParam - callback information. Also we will not use it.
We will call the CreateMiniDump method directly from CurrentDomain_UnhandledException, warning the user about what happened:
public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { System.Windows.Forms.MessageBox.Show("Unhandled exception!"); CreateMiniDump(); }
Run the program
We will check the work of the program by running the collected exe-file and clicking on the button we created:
Run the dump
We received a dump with the .dmp extension. To use it, you just need to open the file, and as a result VisualStudio will start.
A similar menu will appear on the right side of the window:
In order to be able to work with the real program code, and not with the IL code and stack trace, you must specify the symbol paths - the directories in which the pdb files of our application are supposed to be stored. The pdb file contains debug data and project status information. By default, the required files are contained in the same directory as executable files.
Next, by clicking on Debug with mixed, we start the debugging process. We will be able to see the status of the program at the time of the collapse, as well as a warning about the exception that occurred.
Used sources
1.
Stackoverflow
2.
Using Crash Minidump
3.
Howto: C # Generate dump file on crash
4.
Writing Minidumps in C #
The author of the article
A. Fedosin