Воссоздать трассировку стека с номерами строк из отчета об ошибке пользователя в .net? - PullRequest
15 голосов
/ 24 июня 2009

Во-первых, проблема: У меня есть несколько бесплатных проектов, и, как и любое программное обеспечение, они содержат ошибки. Некоторые коллеги-пользователи при обнаружении ошибки присылают мне отчеты об ошибках со следами стека. Чтобы упростить поиск места неисправности, я хочу видеть номера строк в этой трассировке стека. Если приложение поставляется без файлов .pdb, то вся информация о строках теряется, поэтому в настоящее время все мои проекты развернуты с файлами .pdb и, следовательно, сгенерированные трассировки стека имеют эти номера. Но! Но я не хочу видеть эти файлы в дистрибутиве и хочу удалить все .pdb. Они сбивают с толку пользователей, занимают место в установщике и т. Д.

Решение Delphi: Давным-давно, когда я был программистом на Delphi, я использовал следующую технику: в исключительных случаях мое приложение ходило по стеку и собирало адреса. Затем, когда я получил отчет об ошибке, я использовал инструмент, который восстанавливает правильную трассировку стека с именами функций и номерами строк на основе собранных адресов и соответствующих файлов символов, расположенных на МОЕМ компьютере.

Вопрос: Есть ли какая-нибудь библиотека, техника или что-то еще, чтобы сделать то же самое в .NET?

Обновление статуса: Очень интересно, что частое задание вопроса - лучший способ начать собственное расследование. Например, я некоторое время думаю об этой проблеме, но начинаю искать ответ только несколько дней назад.

Вариант 1: MiniDumps. После долгих поисков я нашел способ создать мини-дамп из кода и восстановить стек из управляемого мини-дамп.

Однако для этого решения необходимо перераспределить две дополнительные сборки (размером ~ 1 МБ), и мини-дампы занимают некоторое пространство, и пользователю неудобно отправлять их по электронной почте. Поэтому для моих целей сейчас это неприемлемо.

Вариант 2: Спасибо weiqure за подсказку. Можно извлечь управляемое смещение IL для каждого кадра стека. Теперь проблема в том, как получить номера строк из .pdb на основе этого смещения. И что я нашел:

Используя этот инструмент, можно создавать XML-файлы для каждой сборки выпуска и помещать их в репозиторий. Когда на компьютере пользователя возникает исключение, можно создать отформатированное сообщение об ошибке со смещением IL. Затем пользователь отправляет это сообщение (очень маленькое) по почте. И, наконец, можно создать простой инструмент, который воссоздает полученный стек из отформатированного сообщения об ошибке.

Мне только интересно, почему никто другой не реализует такой инструмент? Я не верю, что это интересно только мне.

Ответы [ 4 ]

14 голосов
/ 24 июня 2009

Вы можете получить смещение последней инструкции MSIL из Исключения, используя System.Diagnostics.StackTrace:

// Using System.Diagnostics
static void Main(string[] args)
{
    try { ThrowError(); }
    catch (Exception e)
    {
        StackTrace st = new System.Diagnostics.StackTrace(e);
        string stackTrace = "";
        foreach (StackFrame frame in st.GetFrames())
        {
            stackTrace = "at " + frame.GetMethod().Module.Name + "." + 
                frame.GetMethod().ReflectedType.Name + "." 
                + frame.GetMethod().Name 
                + "  (IL offset: 0x" + frame.GetILOffset().ToString("x") + ")\n" + stackTrace;
        }
        Console.Write(stackTrace);
        Console.WriteLine("Message: " + e.Message);
    }
    Console.ReadLine();
}

static void ThrowError()
{
    DateTime myDateTime = new DateTime();
    myDateTime = new DateTime(2000, 5555555, 1); // won't work
    Console.WriteLine(myDateTime.ToString());
}

Выход:

в ConsoleApplicationN.exe.Program.Main (смещение IL: 0x7)
в ConsoleApplicationN.exe.Program.ThrowError (смещение IL: 0x1b)
at mscorlib.dll. DateTime..ctor (смещение IL: 0x9)
at mscorlib.dll.DateTime.DateToTicks (смещение IL: 0x61)
Параметры Message: Year, Month и Day описывают непредставимый DateTime.

Затем вы можете использовать Отражатель или ILSpy для интерпретации смещения:

.method private hidebysig static void ThrowError() cil managed
{
    .maxstack 4
    .locals init (
        [0] valuetype [mscorlib]System.DateTime myDateTime)
    L_0000: nop 
    L_0001: ldloca.s myDateTime
    L_0003: initobj [mscorlib]System.DateTime
    L_0009: ldloca.s myDateTime
    L_000b: ldc.i4 0x7d0
    L_0010: ldc.i4 0x54c563
    L_0015: ldc.i4.1 
    L_0016: call instance void [mscorlib]System.DateTime::.ctor(int32, int32, int32)
    L_001b: nop 
    L_001c: ldloca.s myDateTime
    L_001e: constrained [mscorlib]System.DateTime
    L_0024: callvirt instance string [mscorlib]System.Object::ToString()
    L_0029: call void [mscorlib]System.Console::WriteLine(string)
    L_002e: nop 
    L_002f: ret 
}

Вы знаете, что инструкция до 0x1b вызвала исключение. Для этого легко найти код C #:

 myDateTime = new DateTime(2000, 5555555, 1);

Теперь вы можете отобразить код IL на ваш код C #, но я думаю, что выигрыш будет слишком мал, а усилия слишком велики (хотя может быть плагин отражателя). Вы должны быть в порядке со смещением IL.

5 голосов
/ 24 июня 2009

Вы должны использовать Environment.FailFast , вызвать FailFast в Application.UnhandledException и файл дампа будет создан для вас.

Из MSDN:

Метод FailFast записывает запись в журнал в журнал событий приложений Windows используя параметр сообщения, создает дамп вашего приложения, а затем завершает текущий процесс.

Используйте метод FailFast вместо Выход из метода, чтобы прекратить ваше приложение, если состояние вашего приложение повреждено без возможности восстановления, и выполнение вашего приложения блоки try-finally и финализаторы испорченные программные ресурсы. Метод FailFast завершает текущий обрабатывать и выполнять любые CriticalFinalizerObject объекты, но не выполняет никаких активных блоки try-finally или финализаторы.

Вы можете написать простое приложение, которое будет собирать файлы журналов и отправлять их вам.

Теперь открытие файла дампа немного сложнее, Visual Studio не может обработать файл управляемого дампа (исправлено в .NET 4.0), вы можете использовать WinDBG , но вам нужно использовать SOS .

2 голосов
/ 24 июня 2009

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

1 голос
/ 10 августа 2009

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

Microsoft Symbol Server будет индексировать символы отладки и сохранять их для использования в более поздние сроки, когда у вас, например, будет аварийный дамп, и вам понадобятся символы. Вы можете указать Visual Studio или Windbg на свой собственный экземпляр сервера символов, например, Microsoft , и он выведет символы, необходимые для отладки этой версии вашего приложения (при условии, что вы проиндексировали символы с помощью сервера символов). перед отправкой).

Как только у вас появятся соответствующие символы для сборки, вам необходимо убедиться, что у вас есть соответствующие исходные файлы, принадлежащие этой сборке.

Здесь Microsoft Source Server . Как и в случае, когда Symbol Server индексирует символов , исходный сервер будет индексировать source , чтобы убедиться, что у вас есть соответствующие версия исходного кода, принадлежащая сборке программного обеспечения.

Рабочие версии Контроль версий , Сервер символов и Исходный сервер должны быть частью вашей стратегии управления конфигурацией программного обеспечения.

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

Джон Роббинс на PDB-файлах

Джон Роббинс на Исходный сервер

Ознакомьтесь с документацией WinDbg о запуске и запуске Symbol Server.

...