Wspominałem ostatnio o OData scam. Problemie na jaki natrafiłem w WebAPI po tym jak już cały projekt został stworzony. Więc tym tutaj się zajmować nie będę. Zaś opiszę proces w jaki doszedłem do tego, co było nie tak i w jakiej bibliotece to było nie tak – czyli jak za pomocą Visual Studio zdebuggowaliśmy kod i znaleźliśmy przyczynę.
OData składa się z kilku paczek nuget, w zależności od wykorzystania (Web API, WCF, MVC… etc) będzie ich więcej lub mniej. Można oczywiście ściągnąć cały github i mieć kod źródłowy pozwalający zdebuggować nam wszystko. Jednak nie jest to takie łatwe. Sadzę, że postawienie całego środowiska tak by te wszystkie projekty się kompilowały a potem jeszcze by Visual Studio wiedział o symbolach PBP zajęła by ponad dzień.
Kiedyś jedynie co mogliśmy zrobić to po prostu przejrzeć czyiś kod i szukać przyczyny w ten sposób. To nie było wydajne. Problem mógł być na początku drogi jak i w połowie czy pod sam jej koniec. Nie licząc, że za notatki jaka metoda co wywołuje byliśmy odpowiedzialni my :) Na szczęście te czasy minęły .
Teraz wszystko co potrzebujemy to trzy rzeczy:
- Plik PDB
- Visual Studio
- Coś co nam pozwoli z dekompilować kod źródłowy (.NET Refactor, Resharper etc)
Narzędzia generujące PDB z biblioteki
PDB to plik symboli, on określa jakie metody gdzie są dostępne, jak się nazywają itp. Taka ściągawka umożliwiająca aplikacjom jak Visual Studio czy też .NET Framework podać nam więcej informacji na temat biblioteki. Na przykład przy exception dostaniemy linijkę w pliku w którym ten problem wystąpił.
Czasami taki plik jest dostępny publicznie i nie ma problemu z nim, warto sprawdzić czy może a nóż nie istnieje on w katalogu paczek od nuget, a może gdzieś na sieci jest? Na przykład pliki symboli .NET Framework są powszechnie dostępne, dzięki czemu jak chcemy możemy debugować .NET Framework.
Jak go zaś nie ma to musimy się posilać aplikacjami firm trzecich by taki plik wygenerować.
Jednym ze sposobów jest skorzystanie z resharpera. Jeżeli mamy nasz projekt i zajrzymy do jego referencji, to na bibliotece dla której chcemy wygenerować PDB wystarczy kliknąć PPM i dodać ją do Assembly Explorer
:
Następnie w Assembly Explorer
, możemy tą bibliotekę zaznaczyć i wybrać dla niej generowanie PDB:
Po takiej operacji Resharper wygeneruje nam niezbędne pliki za nas. Warto tutaj zaznaczyć, iż jest to robione za pomocą dekompilacji a to znaczy, że nie wszystko musi tutaj być tak piękne jak w normalnym kodzie. Co za tym idzie… może i będzie miało to wpływ na jakoś naszego debugowania – linijka w jedną, linijka w drugą stronę. Jednak mamy plik PDB.
Visual Studio
Tutaj też musimy zrobić kilka rzeczy! :) Po pierwsze, w oknie przy generowaniu PDB podaliśmy folder w którym będziemy przetrzymywać wygenerowane symbole. To na razie wie tylko i wyłącznie Resharper. Musimy o tym poinformować VS. W tym celu otwieramy Tools | Options | Debugging | Symbols
i w polu Cache symbols in this director
y wybieramy podany przez nas katalog:
To jest dość ważne, bez tego, Visual Studio nie będzie wiedział skąd ma pobrać symbole dla bibliotek które chcemy debugować. Jeżeli zaznaczymy Microsoft Symbol Servers
to VS zaciągnie nam z serwera MSowego listę wszystkich PDB dostępnych dla bibliotek Microsoft. Co jest fajne i nie jest. Bo jak debugujemy kod z opcją zewnętrznych bibliotek to MSowe PDB mogą nam nieźle obciążyć system – jak i ogóle spowolnić uruchomienie debugowania kodu.
Modules
(dostępne jedynie w trakcie debugowania: Debug | Windows | Modules
). Wystarczy, że znajdziemy interesujący nas moduł/bibliotekę i za pomocą PPM myszy wybierzemy Load Symbols.Mając symbole, musimy jeszcze zmienić ustawienia debugowania, tak by Visual Studio pozwalał nam na debugowanie nie naszego kodu. Możemy to ustawić w oknie Tools | Options | Debugging | General
– należy odhaczyć trzeba Enable Just My Code
:
Teraz mamy już wszystko by rozpocząć debugowanie kodu.
Debuggowanie kodu
Do tego będziemy już potrzebować coś co nam pozwoli dekompilować kod z poziomu VS. Podobnie jak z PDB, możemy do tego wykorzystać Resharpera. Nie mając możliwości dekompilowania kodu, nie uda nam się wejść w metody gdyż MS tego nie wspiera z poziomu VS (albo ja czegoś nie wiem).
Wystarczy, że otworzymy naszą klasę która nas interesuje i wstawimy tam breakpoint i odpalimy debugowanie:
To wszystko. Teraz trzeba mieć tylko cierpliwość i ustawiać dość często breakpointy. Dzieje się tak gdyż nie mamy gwarancji, że dana linijka w zdekompilowanym kodzie jest taka sama jak w oryginalnym kodzie. Dla przykładu:
W zdekompilowanym kodzie:
public static double? Distance(this Geometry operand1, Geometry operand2) { return GeometryOperationsExtensions.OperationsFor(operand1, operand2).IfValidReturningNullable<SpatialOperations, double>((Func<SpatialOperations, double>) (ops => ops.Distance(operand1, operand2))); } // inny plik public static readonly MethodInfo FloorOfDouble = ClrCanonicalFunctions.MethodOf<double>((Expression<Func<object, double>>) (_ => Math.Floor(0.0)));
W oryginalnym:
public static double? Distance(this Geometry operand1, Geometry operand2) { return OperationsFor(operand1, operand2).IfValidReturningNullable(ops => ops.Distance(operand1, operand2)); } // inny plik: // deklaracja zmiennych public static readonly MethodInfo FloorOfDouble; //w konstruktorze FloorOfDouble = MethodOf(_ => Math.Floor(default(double)));
Podsumowanie
Jak widać z odpowiednimi narzędziami jesteśmy dość szybko dojść do tego co jest nie tak, co nie działa i dlaczego nam to nie działa. Szkoda tylko, że wciąż potrzebujemy narzędzi firm trzecich i nie każdy z tego może skorzystać. Przy aktualnym stanie rzeczy, MS powinien w takim momencie dla swoich produktów wprowadzić ściąganie źródeł z github dla swoich produktów. To po prostu było by wyczes.
Tak jesteśmy ograniczeni. Mimo wszystko, myśląc kilka lat wstecz to i tak jest niezły postęp! Daje on możliwość zorientowania się dość szybko czy jest to coś co jesteśmy wstanie naprawić czy to jest coś co jednak musimy zgłosić na github czy jakoś inaczej.
Zdarzyło wam się debugować już kod zewnętrzny? Wiedzieliście o takiej opcji w VS?
Jak za pomocą Visual Studio odkryć linijkę błędu w bibliotece zewnętrznej – Jakub Gutkowski
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl
Naprawdę dobry myk z tym generowaniem plików PDB przez R#, awesome!!!
Super myk :) jak się o nim dowiedziałem to miałem uśmiech od ucha do ucha :)
“OData składa się z kilku paczek nuget, w zależności od wykorzystania (Web API, WCF, MVC… etc) będzie ich więcej lub mnie.” tutaj tylko literówka ale artykuł bardzo dobry.
?? dzięki i dzięki, poprawione :)
Resharper -> Options -> External Sources -> tick Allow downloading from remote locations i Decompile Methods, polecam, nigdy nie musiałem generować pdb, Resharper sam sobie dociąga/generuje potrzebne pliki w momencie pierwszego F12 w daną metodę z biblioteki zewnętrznej :)
dzięki, sprawdzę!
Z jakiej wersji R# korzystasz, w mojej 8 nie znalazłem w menu kontekstowym tej opcji z Assembly Explorerem ?
sorki, jakoś mi przepadł ten komentarz :( to jest jakaś jedna z nowszych wersji, ale opcja jest dostępna na pewno od ReSharper 10.
Ten post zaoszczędził mi właśnie kilka godzin pracy – dzięki!
?
Comments are closed.