Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating .NET crash dumps automatically

I know how to generate Crash Dump files with ADPlus or DebugDiag, but I'm wondering if there is a way to do this on a customer's computer without installing these tools... specifically, I would like to be able to configure my application (using a registry value, for example) to generate a crash dump in the case of a critical failure. More specifically, I need to be able to do this from a C# application, but I don't mind P/Invoke'ing if necessary. Thanks!

like image 523
Michael Bray Avatar asked Jul 15 '09 21:07

Michael Bray


People also ask

How do I enable crash dumps?

Enable memory dump settingIn Control Panel, select System and Security > System. Select Advanced system settings, and then select the Advanced tab. In the Startup and Recovery area, select Settings. Make sure that Kernel memory dump or Complete memory dump is selected under Writing Debugging Information.

How do I create a crash dump in Visual Studio?

With Just-In-Time Debugging enabled, you can attach the Visual Studio debugger to a crashed process outside of Visual Studio, and then save a dump file from the debugger. See Attach to running processes. To save a dump file: While stopped at an error or breakpoint during debugging, select Debug > Save Dump As.


3 Answers

Note that creating a minidump from inside the "failing" process (or even thread) itself is not trivial or might not be accurate (also MiniDumpWriteDump function's Remarks).

Besides, if your process is in such anger that you might need to write a crash dump, the whole situation is typically so hosed, that even attempting to create a crash dump could cause another crash (situations like hangs aside - but those might be even harder to "catch" from within the current process).

The "best" thing you can do, if you cannot install separate applications on your client's systems, is to start an external process (which could also fail in critical situations!) and let that create a crashdump from your current process (see Superassert.NET from John Robbins). You could even go so far, as to put the external binary into your app resources, extract it from there on startup (as to minimize failure in critical situtations) to disk (if you dare).

like image 173
Christian.K Avatar answered Oct 14 '22 03:10

Christian.K


You can configure Windows Error Reporting (WER) to create a crash dump in a specific directory using the following registry script:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps]
"DumpFolder"="C:\\Dumps"
"DumpCount"=dword:00000064
"DumpType"=dword:00000002
"CustomDumpFlags"=dword:00000000

The dump will go into C:\Dumps with a name that reflects the name of the process that crashed. DumpType=2 gives a full memory dump. DumpType=1 gives a mini dump. On 64 bit machines, you do not need to put these under the Wow32 nodes. WER only uses the non-WOW registry key specified above.

Depending on the type of crash, this method may not work. I have yet to figure out why or which crash types it doesn't catch. Anyone?

like image 17
Charles Avatar answered Oct 14 '22 04:10

Charles


I think if your app is hosed then you might as well take a shot at creating a mini dump file, what's the worst that's going to happen, your app will crash? It's doing that anyway, so you might as well try.
The code in the MSDN forum mentioned by VoiDed seems pretty solid. I needed a VB.Net version so here's a VB version for anyone that might need it:

Friend Class MiniDump
    'Code converted from C# code found here: http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6c8d3529-a493-49b9-93d7-07a3a2d715dc

    Private Enum MINIDUMP_TYPE
        MiniDumpNormal = 0 
        MiniDumpWithDataSegs = 1
        MiniDumpWithFullMemory = 2
        MiniDumpWithHandleData = 4
        MiniDumpFilterMemory = 8
        MiniDumpScanMemory = 10
        MiniDumpWithUnloadedModules = 20
        MiniDumpWithIndirectlyReferencedMemory = 40
        MiniDumpFilterModulePaths = 80
        MiniDumpWithProcessThreadData = 100
        MiniDumpWithPrivateReadWriteMemory = 200
        MiniDumpWithoutOptionalData = 400
        MiniDumpWithFullMemoryInfo = 800
        MiniDumpWithThreadInfo = 1000
        MiniDumpWithCodeSegs = 2000
    End Enum

    <Runtime.InteropServices.DllImport("dbghelp.dll")> _
    Private Shared Function MiniDumpWriteDump( _
         ByVal hProcess As IntPtr, _
         ByVal ProcessId As Int32, _
        ByVal hFile As IntPtr, _
         ByVal DumpType As MINIDUMP_TYPE, _
        ByVal ExceptionParam As IntPtr, _
         ByVal UserStreamParam As IntPtr, _
        ByVal CallackParam As IntPtr) As Boolean
    End Function

    Friend Shared Sub MiniDumpToFile(ByVal fileToDump As String)
        Dim fsToDump As IO.FileStream = Nothing

        If (IO.File.Exists(fileToDump)) Then
            fsToDump = IO.File.Open(fileToDump, IO.FileMode.Append)
        Else
            fsToDump = IO.File.Create(fileToDump)
        End If

        Dim thisProcess As Process = Process.GetCurrentProcess()
        MiniDumpWriteDump(thisProcess.Handle, _
                          thisProcess.Id, _
                          fsToDump.SafeFileHandle.DangerousGetHandle(), _
                          MINIDUMP_TYPE.MiniDumpNormal, _
                          IntPtr.Zero, _
                          IntPtr.Zero, _
                          IntPtr.Zero)
        fsToDump.Close()
    End Sub
End Class

Just make sure you solidly eception handle the calls to it and you should be relatively safe.

like image 8
Scott Avatar answered Oct 14 '22 05:10

Scott