43

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

4

7 回答 7

17

请注意,从“失败”进程(甚至线程)本身创建小型转储并非易事或可能不准确(还有MiniDumpWriteDump函数的备注)。

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

如果您无法在客户端系统上安装单独的应用程序,您可以做的“最好”的事情是启动一个外部进程(在紧急情况下也可能失败!)并让它从您当前的进程中创建一个故障转储(参见Superassert. NET 从约翰罗宾斯)。您甚至可以将外部二进制文件放入您的应用程序资源中,在启动时将其从那里提取(以尽量减少关键情况下的故障)到磁盘(如果您敢的话)。

于 2009-07-16T06:03:54.923 回答
17

您可以使用以下注册表脚本配置 Windows 错误报告 (WER) 以在特定目录中创建故障转储:

Windows 注册表编辑器版本 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows 错误报告\LocalDumps]
"DumpFolder"="C:\\Dumps"
“转储计数”=dword:00000064
“转储类型”=dword:00000002
"CustomDumpFlags"=dword:00000000

转储将进入 C:\Dumps,其名称反映了崩溃进程的名称。DumpType=2 给出完整的内存转储。DumpType=1 给出一个小型转储。在 64 位机器上,您不需要将它们放在 Wow32 节点下。WER 仅使用上面指定的非 WOW 注册表项。

根据崩溃的类型,此方法可能不起作用。我还没有弄清楚为什么或哪些崩溃类型它没有捕捉到。任何人?

于 2011-09-13T18:04:04.290 回答
8

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

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

于 2009-08-06T05:22:23.163 回答
5

您可以在事件中使用P/Invokedbghelp.dllMiniDumpWriteDump功能。AppDomain.UnhandledException

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

在 MSDN 论坛上还有一个帖子,它描述了 P/Invoke 签名和正确用法。

于 2009-07-16T03:31:15.637 回答
5

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

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

除其他事项外。

于 2018-08-30T14:59:29.443 回答
0

根据您需要的信息类型,您可以为AppDomain.UnhandledException事件添加处理程序吗?(我知道这不是您正在寻找的东西,但它绝对可以在客户端机器上使用。)

于 2009-07-15T21:03:07.177 回答
-2

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

于 2009-07-15T21:23:18.977 回答