当前位置 博文首页 > 一线码农:.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案

    一线码农:.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案

    作者:一线码农 时间:2021-05-26 18:25

    一:背景

    1. 讲故事

    最近几天接到了几个crash的求助,可能这几个朋友没玩过怎么去生成dump,只能手把手教,感觉也不是一个办法,所以有必要总结一下,后续再有朋友咨询的话,我就可以把这篇文章丢过去了??????,好了,我大概总结了下面三种方式:

    • procdump -e

    • procdump -> AEDebug

    • Windows Error Reporting

    老读者应该知道,我一直都推崇 procdump 去搞定这些事情,毕竟它是一款可跨平台抓取的强大灵巧工具。

    二: 实现可测试案例

    从 dump 样本来看,web类的程序是最多的,所以这里我就以 Asp.NET MVC 5 作为案例,在 RouteConfig 类中我使用一个Timer不断的抛出异常,目的就是把 w3wp 进程给弄挂掉,参考代码如下:

    
        public class RouteConfig
        {
            public static Timer timer;
            public static void RegisterRoutes(RouteCollection routes)
            {
                timer = new Timer(new TimerCallback(m =>
                {
                    var r = 10 / Convert.ToInt32("0");
                }), null, 60000, 5000);
    
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                );
            }
        }
    
    

    对了,肯定有朋友问:为什么不在 Action 中抛异常,这是因为 Http管道 会把这种异常包装成 http 500,所以就达不到 crash 的效果了。

    接下来把程序部署到 IIS 上并运行,可以清楚的看到 Windows 事件查看器 中成功的记录到了崩溃信息,如下图所示:

    三: 3种抓取方式解析

    1. 使用 procdump -e

    这种方式简单但不太稳定,因为有几个朋友告诉我,procdump在抓取的过程中报错了,原因是进程已退出,不管怎么说这个要看你运气了哈,这里的 -eexception 的简写,具体可参见官方文档: https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump。

    
    -e	Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions.
    
    

    完整的参考命令如下:

    
    C:\Windows\system32>procdump -e -ma -w w3wp E:\test
    
    ProcDump v10.0 - Sysinternals process dump utility
    Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards
    Sysinternals - www.sysinternals.com
    
    Waiting for process named w3wp...
    
    ...
    
    Press Ctrl-C to end monitoring without terminating the process.
    
    [21:12:08] Exception: 04242420
    [21:12:08] Exception: E0434352.CLR
    [21:12:09] Exception: E0434352.CLR
    [21:12:09] Exception: E0434352.CLR
    [21:12:09] Exception: E0434352.CLR
    [21:12:09] Exception: E0434352.CLR
    [21:12:09] Exception: E0434352.CLR
    [21:12:14] Exception: C0000094.INT_DIVIDE_BY_ZERO
    [21:12:14] Unhandled: C0000094.INT_DIVIDE_BY_ZERO
    [21:12:14] Dump 1 initiated: E:\test\w3wp.exe_210525_211214.dmp
    [21:12:14] Dump 1 writing: Estimated dump file size is 326 MB.
    [21:12:15] Dump 1 complete: 326 MB written in 1.2 seconds
    [21:12:15] Dump count reached.
    
    

    从输出信息看已经成功抓取了 dump 文件,如果你的机器有多个 w3wp,可以将其替换成 pid,参考命令如下:

    
    C:\Windows\system32>procdump -e -ma 9320 E:\test
    
    

    2. 将 procdump 作为 AeDebug 的默认调试器

    它的大概运作原理是:当程序出现了未处理异常,此时会激活操作系统的 Win32 unhandled exception filter,这个过滤器会调用注册表中 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug 节点配置的调试器,也就是我的 Procdump,要将 procdump 送到注册表的 AeDebug 节点,可以使用 -i 进行注册。

    
    -i	Install ProcDump as the AeDebug postmortem debugger. Only -ma, -mp, -d and -r are supported as additional options.
    
    

    完整参考命令如下:

    
    C:\Windows\system32>procdump -ma -i E:\test
    
    ProcDump v10.0 - Sysinternals process dump utility
    Copyright (C) 2009-2020 Mark Russinovich and Andrew Richards
    Sysinternals - www.sysinternals.com
    
    Set to:
      HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
        (REG_SZ) Auto     = 1
        (REG_SZ) Debugger = "C:\xcode\soft\Procdump\procdump.exe" -accepteula -ma -j "E:\test" %ld %ld %p
    
    Set to:
      HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
        (REG_SZ) Auto     = 1
        (REG_SZ) Debugger = "C:\xcode\soft\Procdump\procdump.exe" -accepteula -ma -j "E:\test" %ld %ld %p
    
    ProcDump is now set as the Just-in-time (AeDebug) debugger.
    
    

    从输出信息看已经成功将其送入到注册表了,接下来可以打开 注册表编辑器 去验证。

    最后就是把 web 跑起来,1min之后就会成功的看到 E:\test 下的 dump 文件啦,截图如下:

    从图中看有2个dump,具体为什么是2个我就不管了,就怕不生成。??????

    3. 借助 Windows Error Reporting 生成

    它的大概运作原理是借助 windows 自带的 Windows Error Reporting 服务去帮助我们生成程序的 crash dump,要实现的话,必须开启这个服务并且在注册表中配置好你要抓取的exe程序,配置起来有点繁琐,这里有一个bat脚本,直接运行即可,简单粗暴。

    
    SET DMPPATH=E:\test
    SC CONFIG WerSvc START= AUTO
    NET START WerSvc
    ECHO 启用完成
     
    REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger /f
    REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger /f
     
    REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger /f
    REG DELETE HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgManagedDebugger /f
     
    ECHO 删除完成
     
    REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe"  /f
    REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe"  /t REG_SZ  /v DumpFolder /d   %DMPPATH% /f
    REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe"  /t REG_DWORD   /v DumpCount /d  2 /f
    REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe"  /t REG_DWORD   /v DumpType /d  2 /f
     
    ECHO 启用完成
     
    PAUSE 
    
    

    有3个参数需要简单解释一下。

    • DumpFolder: dump的存放路径
    • DumpCount: 最多保留几个 dump 文件
    • DumpType: 0:Custom dump. 1:Mini dump. 2:Full dump

    bat执行完成后,可以到注册表中验证一下。

    接下来把web跑起来,1min之后你就会看到生成的dump文件了,截图如下:

    三:总结

    对于抓取程序crash的dump,这三种方式基本上就可以做到万无一失,总结完后,对你对我都是节省宝贵的时间??????。

    更多高质量干货:参见我的 GitHub: dotnetfly

    图片名称
    bk