Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace Custom.Utilities
{
/// <summary>
/// The MiniDump class used to Write out memory dumps of the current process.
/// For the souce of roughly 75% of this code and related MSDN description: http://blogs.msdn.com/b/dondu/archive/2010/10/24/writing-minidumps-in-c.aspx
/// For extended information on the background design of this class: http://www.debuginfo.com/articles/effminidumps.html
/// </summary>
public sealed class MiniDump
{
/// <summary>
/// Whether a dump is currently being taken
/// </summary>
private static bool currentlyDumping = false;
// Missing XML comment for publicly visible type or member 'Type_or_Member' - exists because a definition is desired on each member of the Typ enum below and suppression is not working.
#pragma warning disable 1591
/// <summary>
/// The listing of flags used for different memory writes.
/// </summary>
[Flags]
public enum Typ : uint
{
// From dbghelp.h:
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
MiniDumpWithFullMemory = 0x00000002,
MiniDumpWithHandleData = 0x00000004,
MiniDumpFilterMemory = 0x00000008,
MiniDumpScanMemory = 0x00000010,
MiniDumpWithUnloadedModules = 0x00000020,
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
MiniDumpFilterModulePaths = 0x00000080,
MiniDumpWithProcessThreadData = 0x00000100,
MiniDumpWithPrivateReadWriteMemory = 0x00000200,
MiniDumpWithoutOptionalData = 0x00000400,
MiniDumpWithFullMemoryInfo = 0x00000800,
MiniDumpWithThreadInfo = 0x00001000,
MiniDumpWithCodeSegs = 0x00002000,
MiniDumpWithoutAuxiliaryState = 0x00004000,
MiniDumpWithFullAuxiliaryState = 0x00008000,
MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
MiniDumpIgnoreInaccessibleMemory = 0x00020000,
MiniDumpValidTypeFlags = 0x0003ffff,
};
// Missing XML comment for publicly visible type or member 'Type_or_Member' - exists because a definition is desired on each member of the Typ enum above.
#pragma warning restore 1591
/// <summary>
/// The structure representing the minidump exception
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable", Justification="Microsoft created method AND suppression"), StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
struct MiniDumpExceptionInformation
{
public uint ThreadId;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
/// <summary>
/// Write out the dump with exception.
/// </summary>
/// <param name="hProcess"></param>
/// <param name="processId"></param>
/// <param name="hFile"></param>
/// <param name="dumpType"></param>
/// <param name="expParam"></param>
/// <param name="userStreamParam"></param>
/// <param name="callbackParam"></param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass", Justification = "Microsoft created method AND suppression"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1414:MarkBooleanPInvokeArgumentsWithMarshalAs"), DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, IntPtr hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
/// <summary>
/// Write out the dump without exception.
/// </summary>
/// <param name="hProcess"></param>
/// <param name="processId"></param>
/// <param name="hFile"></param>
/// <param name="dumpType"></param>
/// <param name="expParam"></param>
/// <param name="userStreamParam"></param>
/// <param name="callbackParam"></param>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass", Justification = "Microsoft created method AND suppression"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1414:MarkBooleanPInvokeArgumentsWithMarshalAs"), DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, IntPtr hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
/// <summary>
/// Retrieves the current thread's ID
/// </summary>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass", Justification = "Microsoft created method AND suppression"), DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
static extern uint GetCurrentThreadId();
/// <summary>
/// Retrieves the current Process
/// </summary>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass", Justification = "Microsoft created method AND suppression"), DllImport("kernel32.dll", EntryPoint = "GetCurrentProcess", ExactSpelling = true)]
static extern IntPtr GetCurrentProcess();
/// <summary>
/// Retrieves the current process's ID
/// </summary>
/// <returns></returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass", Justification = "Microsoft created method AND suppression"), DllImport("kernel32.dll", EntryPoint = "GetCurrentProcessId", ExactSpelling = true)]
static extern uint GetCurrentProcessId();
/// <summary>
/// Write a dump to given location with all flags set, assuming no exception was thrown, and to a default time based log location.
/// </summary>
/// <returns>The successful completion of the dump. Will fail if trying to create a dump while a dump is running.</returns>
public static bool Write()
{
return Write("D:\\data\\Dump-" + DateTime.Now.ToString("yyyyMMdd", CultureInfo.InvariantCulture) + ".dmp");
}
/// <summary>
/// Write a dump to given location with all flags set, assuming no exception was thrown.
/// </summary>
/// <param name="fileName">Where to log to</param>
/// <returns>The successful completion of the dump. Will fail if trying to create a dump while a dump is running.</returns>
public static bool Write(string fileName)
{
return Write(fileName, (uint)(Typ.MiniDumpWithFullMemory | Typ.MiniDumpWithFullMemoryInfo | Typ.MiniDumpWithHandleData | Typ.MiniDumpWithThreadInfo | Typ.MiniDumpWithUnloadedModules), false);
}
/// <summary>
/// Write a dump to given location using the given dump type.
/// </summary>
/// <param name="fileName">Where to log to</param>
/// <param name="dumpTyp">The type of dump to take</param>
/// <param name="exceptionRaised">Whether an unhandled exception was raised to reach here</param>
/// <returns>The successful completion of the dump. Will fail if trying to create a dump while a dump is running.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle", Justification="Calling internal sealed code in this situation is recommended by Microsoft.")]
public static bool Write(string fileName, uint dumpTyp, bool exceptionRaised)
{
if (currentlyDumping)
{
return false;
}
currentlyDumping = true;
using (var fs = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
{
IntPtr proc = GetCurrentProcess();
uint procId = GetCurrentProcessId();
IntPtr handle = fs.SafeFileHandle.DangerousGetHandle();
bool success = false;
if (exceptionRaised)
{
MiniDumpExceptionInformation exp;
exp.ThreadId = GetCurrentThreadId();
exp.ClientPointers = false;
exp.ExceptionPointers = System.Runtime.InteropServices.Marshal.GetExceptionPointers();
success = MiniDumpWriteDump(proc, procId, handle, (uint)dumpTyp, ref exp, IntPtr.Zero, IntPtr.Zero);
}
else
{
success = MiniDumpWriteDump(proc, procId, handle, (uint)dumpTyp, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
}
currentlyDumping = false;
return success;
}
}
}
}
I also have some code to analyze current performance counters as well if anyone cares to see.