Generate dumps on first chance exceptions of multiple instances of an application

3.4k views Asked by At

I would like to generate a dump for first chance exceptions for a specific application that get's launched at random intervals several times a day, running multiple instances at any one time.

What have I tried

Procdump

To use procdump I have to know the PID or wait for the process to launch. As multiple instances get launched, this will not work to start monitoring all the launched instances

gflags

Using gflags I could attach a debugger but I don't want to manually continue each process and I have no idea how to automate the process. I tried using procdump as debugger in gflags but I don't know how to pass the process to procdump.

2

There are 2 answers

1
Thomas Weller On BEST ANSWER

In my comments I was mixing up the %ld parameter from the AeDebug registry setting with that of GFlags. However, AeDebug will not be useful here, since it only comes into play when the application is crashing, which isn't the case here.

I'm using the following demo application to generate some first chance exceptions:

using System;    
namespace ThrowSomeFirstChance
{
    static class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(args[0]);
            try
            {
                throw new ApplicationException("Exception 1");
            }
            catch (Exception){}
            try
            {
                throw new ApplicationException("Exception 2");
            }
            catch (Exception){}
            Console.ReadLine();
        }
    }
}

GFlags + ProcDump

The whole idea of that GFlags setting (which affects the Image File Execution Options registry key) is to run the application under the debugger to really debug all sorts of things right from the start of the application. So if you use the GFlags setting, you can't pass a process ID, since at that time, the process has not been started yet. The process must be started by the debugger.

With the following GFlags setting, ProcDump works fine for me:

E:\debug\procdump.exe -ma -e 1 -n 4 -x e:\debug\dumps

where

  • -ma gets the full memory, which is useful for .NET
  • -e 1 captures first chance exceptions
  • -n 4 specifies a maximum amount of dumps to generate (some applications may generate hundred of exceptions)
  • -x <dump folder> <application> <arguments> specifies the executable to launch

    Note that the -x option seems to be incomplete, but that's ok since Windows will pass the application name and arguments automatically and probably was the reason for the odd order of arguments here.

GFlags settings

GFlags + WinDbg

Doing the same with WinDbg is much more work. You'll need to run WinDbg in the correct bitness to get good results and catching all first chance exceptions isn't simple.

"E:\debug\x86\WinDbg.exe"  -G -Q -c $$<e:\debug\dump.dbg 
  • -G skip the final breakpoint when the application terminates (minimize user interaction)
  • -Q skip the "Save workspace" question (minimize user interaction)
  • -c $$<dump.dbg run a script

    The script will be run at the initial breakpoint, so don't use the -g option (skip initial breakpoint). Instead, set up the things at that time and continue with g. A script may look like

    sxe -c ".dump /ma /u e:\debug\dotnet.dmp;g" clr
    g
    

    However, note that this only covers .NET first chance exceptions and the debugger will wait for input for other exceptions. If you want to get this complete, you'll need to set up commands for all types of exceptions, which is far from convenient (see also this answer).

1
blabb On

wrote a simple powershell script to enumerate pids of multiple instances of same exe and dumped it when exceptions occurs like below

script

$b=($a= Get-Process fkiss).count
0..($b-1)|%{$c = ("-e 1 -n 10 {0}" -f $a[$_].Id);Start-Process procdump $c}  

compiled and double clicked this code twice

#include <stdio.h>
#include <windows.h>
void main (void){
    int i=0,a=2,b=0;
    while (i < 20) {
    __try {
        Sleep(6000);
        printf("%d\n",a/b);
    }__except(EXCEPTION_EXECUTE_HANDLER) {
        b=2;
        printf("%d\n",a/b);
        Sleep(6000);
    }
    i++;
    b=0;
    }
}

got 20 dumps in the directory

powershell -c (get-childitem *.dmp).count
20

and they do reflect both the instances using

for %I in (dir *.dmp) do dumpchk %I | grep -i "-e 1 -n "

output

>dumpchk fkiss.exe_160126_045712.dmp   | grep -i "-e 1 -n "
Loading dump file fkiss.exe_160126_045712.dmp
*** "E:\sysint\procdump.exe" -e 1 -n 10 3084
*** "E:\sysint\procdump.exe" -e 1 -n 10 3084

>dumpchk fkiss.exe_160126_045714.dmp   | grep -i "-e 1 -n "
Loading dump file fkiss.exe_160126_045714.dmp
*** "E:\sysint\procdump.exe" -e 1 -n 10 3108
*** "E:\sysint\procdump.exe" -e 1 -n 10 3108

>dumpchk fkiss.exe_160126_045724.dmp   | grep -i "-e 1 -n "
Loading dump file fkiss.exe_160126_045724.dmp
*** "E:\sysint\procdump.exe" -e 1 -n 10 3084
*** "E:\sysint\procdump.exe" -e 1 -n 10 3084