3

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.

Lieven Keersmaekers
  • 57,207
  • 13
  • 112
  • 146
  • FYI `procdump` can use the process' name, not just the PID. See [the first example](https://technet.microsoft.com/en-us/sysinternals/dd996900.aspx). – Patrick Quirk Jan 25 '16 at 13:38
  • @PatrickQuirk - I know but that's only valid when there's one matching process. In our case, there are multiple instances running. – Lieven Keersmaekers Jan 25 '16 at 13:40
  • What does "gets launched" mean? Can you change the way it gets launched? Can you e.g. replace the exe that gets launched by your own exe that launches `procdump` along with the original process? – Thomas Weller Jan 25 '16 at 14:32
  • @Thomas - good idea but unfortunately, no I can't. Not that we don't have every necesery right to do so but that's simply not allowed and will not be allowed either. – Lieven Keersmaekers Jan 25 '16 at 14:35
  • 1
    Regarding GFlags, you could launch WinDbg, pass the PID as an argument (`c:\path\to\windbg.exe -p %ld`) and pass a script as argument (`-c "$$>a< c:\path\to\catchfirstchance.dbg"`) that performs the inital setup (like `sxe clr`) and steps over the initial breakpoint (`g`). – Thomas Weller Jan 25 '16 at 14:36
  • The `%ld` thing could also work for procdump – Thomas Weller Jan 25 '16 at 14:38
  • Addding `procdump -ma -e 1 %ld` in the debugger section of gflags for notepad.exe and starting notepad gives me following error `No process matching the specified name can be found` I was hoping not having to use windbg for this. The dump should be taken automatically btw. There should be no user intervention. – Lieven Keersmaekers Jan 25 '16 at 14:42
  • Ok, I see. I'll try that at home. You could use `cdb` instead of WinDbg and make sure the debugger exists after recording the crash dump so that there's no user interaction. – Thomas Weller Jan 25 '16 at 14:50
  • Since the application is known upfront, you can use the [IFEO](http://blogs.msdn.com/b/mithuns/archive/2010/03/24/image-file-execution-options-ifeo.aspx) registry key to set the "debugger" value - i.e. define a program that's started instead of the application. This is ideal to hook the debugger (cdb) to your app for monitoring. – deemok Jan 25 '16 at 17:31
  • @deemok - isn't that the same as what gflags does? It's not a debugger I want to start but any one tool that would allow me to monitor the started proces for first chance exceptions, create a dump if one occurs and lets the process continue on it's merry way *(just like procdump does)* – Lieven Keersmaekers Jan 25 '16 at 18:21
  • 1
    @LievenKeersmaekers: ok, that's exactly what you can do with gflags. [Here're](http://forum.sysinternals.com/procdump-via-image-file-execution-option_topic28218.html) detailed instructions on how to achieve this with procdump. – deemok Jan 25 '16 at 20:31
  • @deemok - that looks very promising and would be exactly what I need. I'll give it a try when back at work. Only caveat I can think of right now is that it's passing the executable name and the application is running multiple instances. I'll have to find a way to pass the PID. – Lieven Keersmaekers Jan 25 '16 at 20:33

2 Answers2

3

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
blabb
  • 8,674
  • 1
  • 18
  • 27
  • I have been pondering about this and to let the powershell scripts loop to also catch newly created processes. If the gflags route wouldn't have worked, this would have been the way to go. Thank you blabb. – Lieven Keersmaekers Jan 26 '16 at 06:01
2

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).

Community
  • 1
  • 1
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • Thanks for figuring it out Thomas. Looking back, the one thing that made it work was the `-x` parameter. I didn't specify that in gflags resulting in a cryptic message *(No process matching the specified name)* when starting notepad *(from commandline to view the message)*. – Lieven Keersmaekers Jan 26 '16 at 06:25