我知道如何使用ADPlus或DebugDiag生成Crash Dump文件,但我想知道是否有办法在客户的计算机上执行此操作而不安装这些工具...具体来说,我希望能够配置我的应用程序(例如,使用注册表值)在严重故障的情况下生成崩溃转储。更具体地说,我需要能够从C#应用程序执行此操作,但如果有必要,我不介意P / Invoke。谢谢!
答案 0 :(得分:14)
请注意,从“失败”进程(甚至是线程)本身创建一个minidump并不简单或可能不准确(也是MiniDumpWriteDump函数的备注)。
此外,如果你的进程如此愤怒以至于你可能需要编写一个崩溃转储,整个情况通常是如此模糊,即使尝试创建崩溃转储也可能导致另一次崩溃(例如挂起的情况 - 但那些可能更难以从当前过程中“捕获”。)
如果您无法在客户端系统上安装单独的应用程序,那么您可以做的“最好”的事情就是启动一个外部进程(在关键情况下也可能会失败!)并让它从您当前的进程创建一个崩溃转储(见Superassert.NET from John Robbins)。你甚至可以走得太远,把外部二进制文件放到你的应用程序资源中,在启动时从那里提取它(以最小化关键位置的失败)到磁盘(如果你敢)。
答案 1 :(得分:14)
您可以使用以下注册表脚本配置Windows错误报告(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注册表项。
根据崩溃的类型,此方法可能无效。我还没弄清楚为什么或哪些碰撞类型没有捕获。任何人吗?
答案 2 :(得分:7)
我认为如果您的应用程序已被清除,那么您可能会尝试创建一个迷你转储文件,这将是最糟糕的情况,您的应用程序将崩溃?无论如何它正在这样做,所以你不妨试试。
MSDN forum mentioned by 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
只要确保你能够完全处理对它的调用,你应该相对安全。
答案 3 :(得分:5)
你可以在dbghelp.dll
事件中调用MiniDumpWriteDump
的{{1}}函数。
在这种情况下,您可以转储.NET异常数据的日志并将minidump写入文件。
还有thread on the MSDN forums描述了P / Invoke签名和正确用法。
答案 4 :(得分:0)
根据您需要的信息类型,您可以为AppDomain.UnhandledException
事件添加处理程序? (我知道这不是你想要的,但它肯定可以在客户端机器上使用。)
答案 5 :(得分:0)
您是否使用log4net之类的日志框架?通常,您会关闭发布的调试级别消息。但是,您可以考虑编写一个特殊的appender,它仅在某些情况下(例如崩溃)记录到文件中。这个appender最初写入一个只有内存的ringbuffer,可以写入一个文件,稍后由例如280Z28建议的异常处理程序触发。
答案 6 :(得分:0)
您可以致电Environment.FailFast,该电话将:
FailFast方法将消息字符串写入Windows应用程序事件日志,创建应用程序的转储,然后终止当前进程。该消息字符串也包含在向Microsoft的错误报告中。
还有其他事情。