Автоматическое создание аварийных дампов .NET - PullRequest
40 голосов
/ 16 июля 2009

Я знаю, как генерировать файлы Crash Dump с помощью ADPlus или DebugDiag, но мне интересно, есть ли способ сделать это на компьютере клиента без установки этих инструментов ... в частности, я хотел бы иметь возможность настроить мое приложение (например, с использованием значения реестра) для создания аварийного дампа в случае критического сбоя. Точнее, мне нужно иметь возможность делать это из приложения на C #, но я не против P / Invoke'ing, если это необходимо. Спасибо!

Ответы [ 7 ]

14 голосов
/ 13 сентября 2011

Вы можете настроить Windows Error Reporting (WER) для создания аварийного дампа в определенной директории, используя следующий скрипт реестра:

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

Дамп отправится в C: \ Dumps с именем, которое отражает имя сбойного процесса. DumpType = 2 дает полный дамп памяти. DumpType = 1 дает мини-дамп. На 64-битных машинах вам не нужно размещать их под узлами Wow32. WER использует только ключ реестра, отличный от WOW, указанный выше.

В зависимости от типа сбоя этот метод может не работать. Мне еще предстоит выяснить, почему или какие типы сбоев он не ловит. Кто-нибудь? * * 1006

14 голосов
/ 16 июля 2009

Обратите внимание, что создание минидампа внутри самого "сбойного" процесса (или даже потока) не является тривиальным или может быть неточным (также MiniDumpWriteDump Замечания функции).

Кроме того, если ваш процесс находится в такой ярости, что вам может потребоваться написать аварийный дамп, вся ситуация обычно настолько запутана, что даже попытка создать аварийный дамп может вызвать другой сбой (такие ситуации, как зависание - но может быть еще сложнее «поймать» внутри текущего процесса).

«Лучшее», что вы можете сделать, если вы не можете установить отдельные приложения в системах вашего клиента, - это запустить внешний процесс (который также может завершиться ошибкой в ​​критических ситуациях!) И позволить ему создать аварийный дамп из вашего текущего процесса ( см. Superassert.NET от Джона Роббинса ). Вы могли бы даже пойти так далеко, чтобы поместить внешний двоичный файл в ресурсы вашего приложения, извлечь его оттуда при запуске (чтобы минимизировать ошибки в критических ситуациях) на диск (если вы решитесь).

8 голосов
/ 06 августа 2009

Я думаю, что если ваше приложение подключено к сети, то вы могли бы также попытаться создать файл мини-дамп, что может случиться в худшем случае, ваше приложение вылетит? В любом случае, он делает это, так что вы можете попробовать.
Код на форуме MSDN, упомянутый VoiDed , кажется довольно солидным. Мне нужна была версия VB.Net, так что вот версия VB для всех, кому она может понадобиться:

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

Просто убедитесь, что вы надежно обрабатываете вызовы, и вы должны быть в относительной безопасности.

5 голосов
/ 16 июля 2009

Вы можете использовать функцию P / Invoke dbghelp.dll MiniDumpWriteDump в событии AppDomain.UnhandledException.

В этом случае вы можете вывести журнал данных исключений .NET и записать мини-дамп в файл.

На форумах MSDN также есть ветка , которая описывает сигнатуру P / Invoke и правильное использование.

0 голосов
/ 30 августа 2018

Вы можете позвонить Environment.FailFast , который будет:

Метод FailFast записывает строку сообщения в журнал событий приложений Windows, создает дамп приложения и затем завершает текущий процесс. Строка сообщения также включена в отчет об ошибках в Microsoft.

Среди прочего.

0 голосов
/ 16 июля 2009

Используете ли вы каркасы журналирования, такие как log4net? Обычно вы отключаете сообщения уровня отладки для выпуска. Однако вы можете подумать о написании специального приложения, которое регистрирует файл только в определенных случаях (например, при сбое). Этот appender сначала записывает в кольцевой буфер только для памяти, который может быть записан в файл, позже - запускается, например, обработчиком исключений, как предложено 280Z28.

0 голосов
/ 16 июля 2009

В зависимости от того, какая информация вам нужна, вы можете добавить обработчик для события AppDomain.UnhandledException? (Я знаю, что это не совсем то, что вы ищете, но оно определенно доступно на клиентских компьютерах.)

...