我知道如何使用ADPlus或DebugDiag生成崩溃转储文件,但我想知道是否有一种方法可以在客户的计算机上进行此操作而无需安装这些工具... 具体来说,我希望能够通过配置我的应用程序(例如使用注册表值)在发生严重故障时生成崩溃转储。更具体地说,我需要能够从C#应用程序中实现此操作,但如果必要的话,我不介意使用P/Invoke。谢谢!
我知道如何使用ADPlus或DebugDiag生成崩溃转储文件,但我想知道是否有一种方法可以在客户的计算机上进行此操作而无需安装这些工具... 具体来说,我希望能够通过配置我的应用程序(例如使用注册表值)在发生严重故障时生成崩溃转储。更具体地说,我需要能够从C#应用程序中实现此操作,但如果必要的话,我不介意使用P/Invoke。谢谢!
需要注意的是,从“失败”的进程(甚至线程)内部创建minidump并不容易或可能不准确(另请参阅MiniDumpWriteDump函数的备注)。
此外,如果您的进程处于如此糟糕的状态,以至于您可能需要编写崩溃转储,那么整个情况通常已经非常混乱,即使尝试创建崩溃转储也可能会导致另一个崩溃(除了挂起之类的情况 - 但这些可能更难从当前进程内“捕获”)。
如果您无法在客户系统上安装单独的应用程序,则可以尝试启动外部进程(在关键情况下也可能失败!),并让该进程从当前进程创建一个crashdump(请参见John Robbins的Superassert.NET)。 您甚至可以将外部二进制文件放入应用程序资源中,在启动时从中提取(以尽量减少关键情况下的故障),并将其保存到磁盘上(如果您敢这样做)。
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注册表键。
我认为如果你的应用程序已经崩溃了,那么你不妨试着创建一个小型转储文件,最坏的情况是什么?你的应用程序已经崩溃了吗?反正它已经这样做了,所以你不妨试试。
在VoiDed提到的MSDN论坛中的代码似乎非常可靠。我需要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
只要你能够牢固地处理对它的调用,你就相对安全了。
MiniDumpWriteDump
会导致您的进程死锁,并阻止其终止。 MiniDumpWriteDump
做的第一件事是挂起进程中的所有线程。如果您运气不好,其中一个线程正在分配堆内存。当 MiniDumpWriteDump
尝试分配堆内存时,它将无限期地等待锁被释放,但锁被挂起的线程所持有。在进程中进行这种操作是不安全的。 - IInspectableMINIDUMP_TYPE
中所有的值都是十六进制的,所以在 VB 中应该加上 &H
前缀。 - PeterJ除其他事项外。FailFast方法将消息字符串写入Windows应用程序事件日志,创建应用程序的转储,然后终止当前进程。消息字符串也包含在向Microsoft报告错误中。
您可以在AppDomain.UnhandledException
事件中调用dbghelp.dll
的MiniDumpWriteDump
函数。
在此事件中,您可以转储.NET异常数据并将minidump写入文件。
MSDN论坛上也有一个线程描述了P/Invoke签名和正确用法。
根据您需要的信息类型,您可以为AppDomain.UnhandledException
事件添加处理程序吗?(我知道这不完全是您要找的,但它绝对可用于客户端机器。)