Подтвердить что ты не робот

Автоматическое создание аварийных отказов .NET

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Вы можете настроить отчет об ошибках Windows (WER) для создания дампа сбоя в определенном каталоге, используя следующий реестр 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

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

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

Ответ 3

Я думаю, что если ваше приложение будет закрыто, вы также можете сделать снимок при создании файла мини-дампа, что самое худшее, что произойдет, ваше приложение выйдет из строя? Это все равно, так что вы можете попробовать.
Код в форуме 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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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