using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Common { public static class MiniDump { [Flags] public enum Option : uint { Normal = 0x00000000, WithDataSegs = 0x00000001, WithFullMemory = 0x00000002, WithHandleData = 0x00000004, FilterMemory = 0x00000008, ScanMemory = 0x00000010, WithUnloadedModules = 0x00000020, WithIndirectlyReferencedMemory = 0x00000040, FilterModulePaths = 0x00000080, WithProcessThreadData = 0x00000100, WithPrivateReadWriteMemory = 0x00000200, WithoutOptionalData = 0x00000400, WithFullMemoryInfo = 0x00000800, WithThreadInfo = 0x00001000, WithCodeSegs = 0x00002000, WithoutAuxiliaryState = 0x00004000, WithFullAuxiliaryState = 0x00008000, WithPrivateWriteCopyMemory = 0x00010000, IgnoreInaccessibleMemory = 0x00020000, ValidTypeFlags = 0x0003ffff, } enum ExceptionInfo { None, Present } [StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64! struct MiniDumpExceptionInformation { public uint ThreadId; public IntPtr ExceptionPointers; [MarshalAs(UnmanagedType.Bool)] public bool ClientPointers; } // MiniDumpWriteDump function declarations [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam); [DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam); [DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] static extern uint GetCurrentThreadId(); static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo, Exception exception = null) { Process currentProcess = Process.GetCurrentProcess(); IntPtr currentProcessHandle = currentProcess.Handle; uint currentProcessId = (uint)currentProcess.Id; MiniDumpExceptionInformation exp; exp.ThreadId = GetCurrentThreadId(); exp.ClientPointers = false; exp.ExceptionPointers = IntPtr.Zero; if (exceptionInfo == ExceptionInfo.Present && exception != null) { // Get exception pointers exp.ExceptionPointers = Marshal.GetExceptionPointers(); } // Write dump bool result = exp.ExceptionPointers == IntPtr.Zero ? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) : MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero); if (exception != null) { } return result; } public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal, Exception exception = null) { var path = Path.Combine(Environment.CurrentDirectory, dmpPath); var dir = Path.GetDirectoryName(path); if (dir != null && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } using (var fs = new FileStream(path, FileMode.Create)) { return Write(fs.SafeFileHandle, dmpType, exception == null ? ExceptionInfo.None : ExceptionInfo.Present, exception); } } } }