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