Генерировать дампы при первых случайных исключениях нескольких экземпляров приложения.

Я хотел бы создать дамп для исключений первого шанса для конкретного приложения, которое запускается через случайные промежутки времени несколько раз в день, запуская несколько экземпляров в любой момент времени.

Что я пробовал

Procdump

Чтобы использовать procdump, мне нужно знать PID или дождаться запуска процесса. При запуске нескольких экземпляров это не сработает, чтобы начать мониторинг всех запущенных экземпляров.

gflags

Используя gflags, я мог бы подключить отладчик, но я не хочу вручную продолжать каждый процесс, и я понятия не имею, как автоматизировать этот процесс. Я пытался использовать procdump в качестве отладчика в gflags, но не знаю, как передать процесс в procdump.


person Lieven Keersmaekers    schedule 25.01.2016    source источник
comment
FYI procdump может использовать имя процесса, а не только PID. См. первый пример.   -  person Patrick Quirk    schedule 25.01.2016
comment
@PatrickQuirk - я знаю, но это справедливо только при наличии одного процесса сопоставления. В нашем случае запущено несколько экземпляров.   -  person Lieven Keersmaekers    schedule 25.01.2016
comment
Что значит запускается? Можно ли изменить способ запуска? Можете ли вы, например. заменить исполняемый файл, который запускается, вашим собственным исполняемым файлом, который запускает procdump вместе с исходным процессом?   -  person Thomas Weller    schedule 25.01.2016
comment
@Thomas - хорошая идея, но, к сожалению, нет, я не могу. Не то чтобы у нас не было на это всех необходимых прав, но это просто не разрешено и не будет разрешено.   -  person Lieven Keersmaekers    schedule 25.01.2016
comment
Что касается GFlags, вы можете запустить WinDbg, передать PID в качестве аргумента (c:\path\to\windbg.exe -p %ld) и передать скрипт в качестве аргумента (-c "$$>a< c:\path\to\catchfirstchance.dbg"), который выполняет первоначальную настройку (например, sxe clr) и переходит через начальную точку останова (g).   -  person Thomas Weller    schedule 25.01.2016
comment
%ld тоже может работать для procdump   -  person Thomas Weller    schedule 25.01.2016
comment
Добавление procdump -ma -e 1 %ld в раздел отладчика gflags для notepad.exe и запуск блокнота дает мне следующую ошибку No process matching the specified name can be found Я надеялся, что для этого не придется использовать windbg. Кстати, дамп должен сниматься автоматически. Не должно быть никакого вмешательства пользователя.   -  person Lieven Keersmaekers    schedule 25.01.2016
comment
Хорошо, я вижу. Я попробую это дома. Вы можете использовать cdb вместо WinDbg и убедиться, что отладчик существует после записи аварийного дампа, чтобы пользователь не вмешивался.   -  person Thomas Weller    schedule 25.01.2016
comment
Поскольку приложение известно заранее, вы можете использовать IFEO для установки значения отладчика, т.е. определения программы, которая запускается вместо приложения. Это идеально подходит для подключения отладчика (cdb) к вашему приложению для мониторинга.   -  person deemok    schedule 25.01.2016
comment
@deemok - разве это не то же самое, что и gflags? Это не отладчик, который я хочу запустить, а любой инструмент, который позволит мне отслеживать запущенные процессы на наличие исключений первого шанса, создавать дамп, если он возникает, и позволять процессу продолжаться своим веселым путем (как это делает procdump)   -  person Lieven Keersmaekers    schedule 25.01.2016
comment
@LievenKeersmaekers: хорошо, это именно то, что вы можете сделать с gflags. здесь подробные инструкции о том, как это сделать с процдампом.   -  person deemok    schedule 25.01.2016
comment
@deemok - это выглядит очень многообещающе и было бы именно тем, что мне нужно. Я попробую, когда вернусь на работу. Единственное предостережение, о котором я могу думать прямо сейчас, это то, что он передает имя исполняемого файла, и приложение работает в нескольких экземплярах. Мне нужно найти способ передать PID.   -  person Lieven Keersmaekers    schedule 25.01.2016


Ответы (2)


В своих комментариях я перепутал параметр %ld из ссылки AeDebug с параметром GFlags. Однако AeDebug здесь бесполезен, так как он вступает в игру только при сбое приложения, а здесь это не так.

Я использую следующее демонстрационное приложение для создания некоторых исключений первого шанса:

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

Вся идея этого параметра GFlags (который влияет на ключ реестра Image File Execution Options) состоит в том, чтобы запустить приложение под отладчиком, чтобы действительно отлаживать все виды вещей с самого начала приложения. Поэтому, если вы используете параметр GFlags, вы не можете передать идентификатор процесса, так как в это время процесс еще не запущен. Процесс должен запускаться отладчиком.

Со следующей настройкой GFlags у меня отлично работает ProcDump:

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

где

  • -ma получает всю память, что полезно для .NET
  • -e 1 фиксирует исключения первого шанса
  • -n 4 указывает максимальное количество генерируемых дампов (некоторые приложения могут генерировать сотни исключений)
  • -x <dump folder> <application> <arguments> указывает исполняемый файл для запуска

    Обратите внимание, что параметр -x кажется неполным, но это нормально, поскольку Windows будет автоматически передавать имя приложения и аргументы, что, вероятно, и является причиной нечетного порядка аргументов здесь.

Настройки GFlags

GFlags + WinDbg

Делать то же самое с WinDbg гораздо сложнее. Вам нужно будет запустить WinDbg с правильной разрядностью, чтобы получить хорошие результаты, а перехватить все исключения первого шанса непросто.

"E:\debug\x86\WinDbg.exe"  -G -Q -c $$<e:\debug\dump.dbg 
  • -G пропустить последнюю точку останова при завершении работы приложения (свести к минимуму взаимодействие с пользователем)
  • -Q пропустить вопрос "Сохранить рабочее пространство" (свести к минимуму взаимодействие с пользователем)
  • -c $$<dump.dbg запустить скрипт

    Сценарий будет запущен в начальной точке останова, поэтому не используйте параметр -g (пропустить начальную точку останова). Вместо этого настройте все в это время и продолжайте с g. Скрипт может выглядеть как

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

    Однако обратите внимание, что это относится только к исключениям первого шанса .NET, и отладчик будет ожидать ввода для других исключений. Если вы хотите завершить это, вам нужно настроить команды для всех типов исключений, что далеко не удобно (см. Также этот ответ).

person Thomas Weller    schedule 25.01.2016
comment
Спасибо, что разобрался, Томас. Оглядываясь назад, можно сказать, что единственной вещью, которая заставляла его работать, был параметр -x. Я не указал это в gflags, что привело к загадочному сообщению (Нет процесса, соответствующего указанному имени) при запуске блокнота (из командной строки для просмотра сообщения). - person Lieven Keersmaekers; 26.01.2016

написал простой скрипт powershell для перечисления pids нескольких экземпляров одного и того же исполняемого файла и сбросил его, когда возникают исключения, как показано ниже.

сценарий

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

скомпилирован и дважды щелкнул этот код

#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;
    }
}

получил 20 дампов в каталоге

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

и они отражают оба экземпляра, использующие

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

вывод

>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
person blabb    schedule 25.01.2016
comment
Я размышлял об этом и о том, чтобы цикл сценариев powershell также перехватывал вновь созданные процессы. Если бы маршрут gflags не работал, это был бы путь. Спасибо блабб. - person Lieven Keersmaekers; 26.01.2016