自动生成 .NET 故障转储

发布于 2024-07-27 13:09:46 字数 184 浏览 13 评论 0原文

我知道如何使用 ADPlus 或 DebugDiag 生成故障转储文件,但我想知道是否有一种方法可以在客户的计算机上执行此操作而无需安装这些工具...具体来说,我希望能够配置我的应用程序(例如,使用注册表值)在发生严重故障时生成故障转储。 更具体地说,我需要能够从 C# 应用程序执行此操作,但我不介意在必要时进行 P/Invoke'ing。 谢谢!

I know how to generate Crash Dump files with ADPlus or DebugDiag, but I'm wondering if there is a way to do this on a customer's computer without installing these tools... specifically, I would like to be able to configure my application (using a registry value, for example) to generate a crash dump in the case of a critical failure. More specifically, I need to be able to do this from a C# application, but I don't mind P/Invoke'ing if necessary. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

谁对谁错谁最难过 2024-08-03 13:09:46

请注意,从“失败”进程(甚至线程)本身内部创建小型转储并不简单,或者可能不准确(也MiniDumpWriteDump 函数的备注)。

此外,如果您的进程如此愤怒以至于您可能需要编写故障转储,则整个情况通常会非常糟糕,甚至尝试创建故障转储也可能导致另一次崩溃(例如挂起的情况 - 但这些甚至可能是更难从当前进程中“捕获”)。

如果您无法在客户端系统上安装单独的应用程序,您可以做的“最好”的事情是启动一个外部进程(在危急情况下也可能失败!)并让它从当前进程创建故障转储(请参阅< href="https://web.archive.org/web/20090825040700/http://msdn.microsoft.com/en-us/magazine/cc188701.aspx" rel="noreferrer">来自 John Robbins 的 Superassert.NET< /a>)。 您甚至可以走得更远,将外部二进制文件放入您的应用程序资源中,在启动时将其从那里提取(以最大限度地减少关键情况下的故障)到磁盘(如果您敢的话)。

Note that creating a minidump from inside the "failing" process (or even thread) itself is not trivial or might not be accurate (also MiniDumpWriteDump function's Remarks).

Besides, if your process is in such anger that you might need to write a crash dump, the whole situation is typically so hosed, that even attempting to create a crash dump could cause another crash (situations like hangs aside - but those might be even harder to "catch" from within the current process).

The "best" thing you can do, if you cannot install separate applications on your client's systems, is to start an external process (which could also fail in critical situations!) and let that create a crashdump from your current process (see Superassert.NET from John Robbins). You could even go so far, as to put the external binary into your app resources, extract it from there on startup (as to minimize failure in critical situtations) to disk (if you dare).

梦在深巷 2024-08-03 13:09:46

您可以配置 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 注册表项。

根据崩溃的类型,此方法可能不起作用。 我还没有弄清楚它无法捕获的原因或崩溃类型。 任何人?

You can configure Windows Error Reporting (WER) to create a crash dump in a specific directory using the following registry 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

The dump will go into C:\Dumps with a name that reflects the name of the process that crashed. DumpType=2 gives a full memory dump. DumpType=1 gives a mini dump. On 64 bit machines, you do not need to put these under the Wow32 nodes. WER only uses the non-WOW registry key specified above.

Depending on the type of crash, this method may not work. I have yet to figure out why or which crash types it doesn't catch. Anyone?

香橙ぽ 2024-08-03 13:09:46

我认为如果你的应用程序被软管攻击,那么你不妨尝试创建一个迷你转储文件,最糟糕的情况是什么,你的应用程序会崩溃吗? 无论如何,它正在这样做,所以你不妨尝试一下。
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

只要确保您可靠地处理对它的调用,您就应该相对安全。

I think if your app is hosed then you might as well take a shot at creating a mini dump file, what's the worst that's going to happen, your app will crash? It's doing that anyway, so you might as well try.
The code in the MSDN forum mentioned by VoiDed seems pretty solid. I needed a VB.Net version so here's a VB version for anyone that might need it:

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

Just make sure you solidly eception handle the calls to it and you should be relatively safe.

椒妓 2024-08-03 13:09:46

您可以在 AppDomain.UnhandledException 事件中 P/Invoke dbghelp.dllMiniDumpWriteDump 函数。

在这种情况下,您可以转储 .NET 异常数据的日志并将小型转储写入文件。

MSDN 上还有一个 线程论坛,其中描述了 P/Invoke 签名和正确用法。

You could P/Invoke dbghelp.dll's MiniDumpWriteDump function in the AppDomain.UnhandledException event.

In this event you could dump a log of the .NET exception data and write a minidump to file.

There's also a thread on the MSDN forums which describes the P/Invoke signature and proper usage.

情徒 2024-08-03 13:09:46

您可以调用 Environment.FailFast,这将:

FailFast 方法将消息字符串写入 Windows 应用程序事件日志,创建应用程序的转储,然后终止当前进程。 该消息字符串还包含在向 Microsoft 报告的错误中。

除其他事项外。

You can call Environment.FailFast, which will:

The FailFast method writes the message string to the Windows Application event log, creates a dump of your application, and then terminates the current process. The message string is also included in error reporting to Microsoft.

Among other things.

离笑几人歌 2024-08-03 13:09:46

根据您需要的信息类型,您可以为 AppDomain.UnhandledException 事件添加处理程序? (我知道这并不完全是您正在寻找的,但它肯定可以在客户端计算机上使用。)

Depending on what kind of information you need, you could add a handler for the AppDomain.UnhandledException event? (I know it's not exactly what you're looking for, but it's definitely available on the client machines.)

过度放纵 2024-08-03 13:09:46

你使用像 log4net 这样的日志框架吗? 通常,您会关闭某个版本的调试级别消息。 但是,您可以考虑编写一个特殊的附加程序,仅在某些情况下(例如崩溃)记录到文件。 该附加程序首先写入仅内存的环形缓冲区,该缓冲区可以写入文件,稍后 - 例如由 280Z28 建议的异常处理程序触发。

Do you use a logging framework like log4net? Normally you switch off debug-level messages for a release. However you can think about writing a special appender which logs to a file only in certain cases (like a crash). This appender writes at first into a memory-only ringbuffer which can be written to a file, later - triggered for instance by a exceptionhandler like suggested by 280Z28.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文