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ę:
(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.
Dzięki wielkie za ten wpis!
Przydaje się.
Pozdrawiam,
Paweł
Comments are closed.