Ostatnio musiałem przekazać klientowi częściowo gotową aplikację zanim jednak to zrobiłem poprosiłem znajomego by ją odpalił u siebie i zobaczył czy wszystko mu śmiga (to, że mi na komputerach w domu działa to nic dziwnego).

Dobrze się złożyło, gdyż niestety aplikacja się nie uruchomiła :) co lepsze dodała do Windows Event Log błąd Windows Error Reporting o ID 1001. Mimo usilnych prób u siebie nie byłem wstanie problemu z reprodukować – suma sumarum okazało się, że wina leży w jednej DLLce, która u mnie była w GAC a u znajomego jej nie było (no i słusznie, że jej tam nie było :), najgorsze z tego było to, że z tej DLLki korzystałem w metodzie obsługującej unhandled exception:)

Jednakże błąd, który znajomy mi pokazał bardzo mnie zaciekawił – głownie, dlatego by w przyszłości wiedzieć jak go czytać i rozumieć. W przybliżeniu wyglądał on tak:

Fault bucket 1039438065, type 5
Event Name: CLR20r3
Response: Not available
Cab Id: 0

Problem signature:
P1: watsonbucketmain.exe
P2: 1.0.0.0
P3: 4b9d671c
P4: WatsonBucketMain
P5: 1.0.0.0
P6: 4b9d671c
P7: 4
P8: 11
P9: System.ArgumentNullException
P10:

Błąd powyżej jest błędem z przykładowej aplikacji do pobrania stąd. To co powyżej widzicie to tak zwany Watson Bucket, lub inaczej Fault Bucket który w pierwszej linijce zawiera ID po którym pomoc MS jest wstanie wam udzielić odpowiedzi.

To co jest w sekcji problem signature pochodzi z integracji CLR z WER i to właśnie ta część najbardziej mnie zainteresowała. Jak widać na pierwszy rzut oka można kilka informacji zgadnąć :) jednak co to jest to P3, P6, P7 i P8?

Zgodnie z tym co udało mi się znaleźć w sieci to sytuacja wygląda następująco:

  • P1 – nazwa aplikacji;
  • P2 – to wersja aplikacji;
  • P3 – Timestamp pliku wykonywalnego (czyli naszego P1);
  • P4 – nazwa assembly/modułu;
  • P5 – wersja assembly który wywołał błąd;
  • P6 – timestamp modułu w którym wystąpił błąd;
  • P7 – to jest token definicji metody (MethodDef, strona 127 jak sprawdzałem) pozbawiony High Byte (nie wiem jak to Podolsku powiedzieć, chodzi o to, że mając dwu bajtowy ciąg, to high byte jest ten po lewej a low byte ten po prawej);
  • P8 – jest to offset instrukcji IL;
  • P9 – wyjątek, jaki został zwrócony;
  • P10 – nie udało mi się do tego dotrzeć :) jak ktoś wie niech powie :)

Czyli dla przykładowego kodu:

using System;
using Module;

namespace WatsonBucketMain
{
    class Program
    {
        static void Main(string[] args)
        {
            ThrowsError p = new ThrowsError();
            p.Run();

            new ModuleA().AndIWillThrow("some string");
        }
    }

    public class ThrowsError
    {
        public void Run()
        {
            IThrowException();
        }

        private void IThrowException()
        {
            Console.WriteLine("I will throw an excpetion :)");
            throw new ArgumentNullException();
        }
    }
}

Zostanie nam zwrócony błąd jaki wkleiłem wyżej.

Teraz cały bajer polega na tym by znaleźć tą linijkę, która nas interesuje – która wywołała błąd. Możemy to zrobić za pomocą narzędzia ILDasm, otwieramy aplikację, przerzucamy drag-n-drop pliki EXE lub jak ktoś woli korzystamy z opcji Open (Ctrl+O) i od razu klikamy Ctrl+M (pokazuje to MetaInfo, View -> MetaInfo -> Show!). Tak przygotowani możemy zaczynać szybką i zwięzłą analizę:

error

(kliknij aby powiększyć)

Teraz przynajmniej jak dostanę tak jak to mój znajomy nazwał „Chesz listę z P?” :) to przynajmniej będę wiedział, co mogę na szybko zrobić by się dowiedzieć, dlaczego błąd wystąpił.

Jeszcze raz, kod dla przykładu dostępny jest tutaj.

1 KOMENTARZ

Comments are closed.