views:

2105

answers:

5

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!

A: 

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

280Z28
A: 

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
+2  A: 

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.

VoiDeD
+3  A: 

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

Christian.K
+2  A: 

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.

Scott