44

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!

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Michael Bray
  • 14,998
  • 7
  • 42
  • 68

7 Answers7

17

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).

mbx
  • 6,292
  • 6
  • 58
  • 91
Christian.K
  • 47,778
  • 10
  • 99
  • 143
  • While there is wisdom is being careful with your actions during an application crash, it's also good to think about what your application is accomplishing. If you're in production, be VERY careful -- However, if you're writing a batch processing application, you're almost certainly better off creating the minidump for debugging purposes later instead of having to do a time-consuming repro. General advice: always consider your situation before making a design decision and be wary of overly broad advice. – jhclark Jan 10 '17 at 17:38
  • @jhclark I'm totally _not_ against writing a mini/crash dump; in fact a _proper_ dump is the best post mortem analysis tool one can ask for. But the point is not attempting to write it from _within_ the victim process. As that is generally unreliable. Having some sort of external watchdog process is the way to go (even something like Sysinternals procdump might do for in-house situations). IMHO that is true regardless of the kind of application or what is trying to accomplish. – Christian.K Jan 11 '17 at 05:50
17

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?

Charles
  • 2,642
  • 3
  • 33
  • 53
  • 3
    As mentioned here (http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx) I don't thing this works for managed code. – uli78 Jan 05 '12 at 09:47
  • 2
    "Applications that do their own custom crash reporting, including .NET applications, are not supported by this feature" – Peter Ritchie Jul 01 '14 at 16:37
  • 11
    I have tried this, and it **does work for managed code** - in my test-case it was framework 4.5. But I had to use the following statement in my .net App: Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); – frank koch Aug 05 '15 at 06:02
  • 2
    The MSDN article is not correct: this works for managed apps, too. Tested on Windows 10 RS4, but I seem to recall that it worked on Windows 8, too. – White hawk May 24 '18 at 11:05
  • Works for non-GUI .net apps too (ie where Application.SetUnhandledExceptionMode() not possible) - tested on Windows Service (via TopShelf), .net 4.6, Windows 10 + Server 2008 R2 – piers7 Aug 28 '18 at 00:10
  • Worked for a VB.NET Winforms application, I had to turn off Application Framework in Project Properties, write the new entry point and add @frankkoch suggestion, and ensure that the DumpType is set to generate full dumps. This still doesn't work for raised Exceptions but it does work for program generated exceptions. – Burhan Jul 16 '21 at 16:56
8

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.

Marc
  • 9,012
  • 13
  • 57
  • 72
Scott
  • 4,113
  • 6
  • 37
  • 49
  • 3
    *"What's the worst that's going to happen, your app will crash?"* - That's not the worst that could happen. A far worse scenario would be that calling `MiniDumpWriteDump` deadlocks your process, and prevents it from terminating. One of the first things that `MiniDumpWriteDump` does is to suspend all threads in the process. If you are unlucky, one of those threads was in the middle of allocating heap memory. And when `MiniDumpWriteDump` tries to allocate heap memory, it will indefinitely wait for the lock to be released, but it's held by a suspended thread. You cannot safely do this in-process. – IInspectable Jan 19 '16 at 05:37
  • 1
    Could you kill the process in this state? If this works in 99% of the crashes and deadlocks in 1% where all the user has to do is force kill I think it is a fair trade off, circumstances dependent. Would starting up a new process from the crashed process work? – Joel McBeth Sep 08 '16 at 18:45
  • 1
    This works well but I noticed in `MINIDUMP_TYPE` all the values are in hex so should have a `&H` prefix for VB. – PeterJ Apr 03 '18 at 05:34
5

You could P/Invoke dbghelp.dll's MiniDumpWriteDump function in the AppDomain.UnhandledException event.

In this event you could dump a log of the .NET exception data and write a minidump to file.

There's also a thread on the MSDN forums which describes the P/Invoke signature and proper usage.

Ryan Stecker
  • 828
  • 13
  • 25
  • 3
    No, [you cannot safely do this](http://stackoverflow.com/questions/1134048/generating-net-crash-dumps-automatically/1135666#comment57477239_1237097). `MiniDumpWriteDump` **must** be called from a separate process. – IInspectable Jan 19 '16 at 05:44
5

You can call Environment.FailFast, which will:

The FailFast method writes the message string to the Windows Application event log, creates a dump of your application, and then terminates the current process. The message string is also included in error reporting to Microsoft.

Among other things.

jack
  • 51
  • 1
  • 1
0

Depending on what kind of information you need, you could add a handler for the AppDomain.UnhandledException event? (I know it's not exactly what you're looking for, but it's definitely available on the client machines.)

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
-2

Do you use a logging framework like log4net? Normally you switch off debug-level messages for a release. However you can think about writing a special appender which logs to a file only in certain cases (like a crash). This appender writes at first into a memory-only ringbuffer which can be written to a file, later - triggered for instance by a exceptionhandler like suggested by 280Z28.

tanascius
  • 53,078
  • 22
  • 114
  • 136
  • 1
    A mini dump is **way** more helpful, than logfiles. It captures the complete state of an application, at the very point an uncaught exception is thrown. You can load it up in a debugger, and get full symbolic information, conveniently linked to source code, full stack traces of all threads, the precise fault location, information on loaded modules, memory, and any number of custom information you feel like adding. – IInspectable Jan 19 '16 at 05:53