Skip to main content

Base Visual Studio debugging functionalities

Cred ca un programator intr-o zi normala de lucru, are nevoie cel putin odata pe zi sa faca debug la cod. Visual Studio are extrem de multe functionalitati care pot sa fie utile in procesul de debug. Din pacate, dupa o perioada de timp uitam de toate feature-urile pe care le avem la dispozitie. In acest post o sa incerc sa trec peste o parte din aceste feature. In prima parte a postului o sa folosesc Visual Studio 2010, iar Visual Studio 2012 o sa folosesc doar pentru cele specifice la Visual Studio 2012.
In mod normal pentru a putea face debug trebuie sa rulam proiectul nostru in dubug. Acest lucru se poate face folosind tasta F5 sau apasand butonul "Start Debugging" din meniul "Debug". In cazul in care procesul nostru deja ruleaza este nevoie sa ne atasam la proces. Acest lucru se face din meniu "Debug-> Attach to Process" sau prin combinatia de taste "Alt+Ctrl+P". 
Puteti sa va atasati la unul sau mai multe procese. In cazul in care nu gasiti procesul in lista, inseamna ca acesta ruleaza sub un alt user sau in alta sesiune. Pentru a putea vedea si acest procese este nevoie sa selectati checkbox-ul "Show processes from all users" sau "Show processes in all sessions". In cazul in care proiectul la care va atasati nu este 1 la 1 cu versiunea pe care o aveti deschisa s-ar putea ca sa nu puteti intra in toate brakepoint-urile pe care le adaugati. In cazul in care adaugati brakepoint-uri si observati ca dupa ce v-ati atasat la proces, acestea au un cerculet rosu si cu un semnul exclamarii langa ele, inseamna ca sursa si versiunea la aplicatie la care faceti debug nu este 1 la 1. Pentru a putea totusi sa faceti debug este nevoie sa debifati optiunea "Require source files to exactly match the original version" din "Tools->Options".
Aceiasi optiune, pentru a accepta ca codul din solutia deschisa sa fie diferit fata de cel care ruleaza poate sa fie gasit data dati click pe breakpoint si selectati optiunea "Location". In aceasta fereastra o sa puteti selecta locatia unde breakpoit-ul este adaugat.
Daca tot am inceput cu optiunile pe care le avem pe un breakpoint, o sa continui si cu restul. Urmatoarea optiune este de adaugare de conditii la breakpoint. Pe baza acestor conditii, putem seta daca aplicatia sa se opreasca la un breakpoint sau nu. Putem sa adaugam orice fel de conditie, iar vestea buna ca avem intelliSense in acest loc, a.i. ne este foarte usor sa definim una sau mai multe conditii legate prin &&, ||. Optiunea de "Has changes" este foarte utila cand vrem ca sa intram in breakpoint cand valoarea conditiei s-a schimbat. In acest caz valoare nu trebuie sa fie obligatoriu de tip boolean.
Urmatorul setup pe care il putem face la un breakpoint este sa setam un contor pentru hits counter. By default, la fiecare atingere a unui breakpoint cand conditia este sadifacuta, aplicatia o sa se opreasca la breakpoint. Dar sunt cazuri cand vrem sa specificam doar la primele 3 sa se opreasca sau cand aceasta valoare este mai mare decat 10.
In cazul in care vrem ca un breakpoint sa fie activ doar pe anumite thread-uri sau doar pe anumite procese (cazul in care suntem atasati la mai multe procese) putem sa ne folosim de urmatoarea optiune care apare in meniul unui breakpoint - "Filter". Putem sa setam ca un breakpoint sa intre doar pe un thread cu un anumit id sau nume sau doar daca ruleaza pe o anumita masina. In exemplul de mai jos, doar in cazul in threadul se numeste "CustomThread"  si rulam pe o masina cu numele "W8" breakpointul o sa fie activ.
Urmatorul lucru pe care il putem seta este un macro care sa se execute cand breakpointul este lovit sau sa afisam un anumit mesaj. Pana in momentul de fata nu am avut nevoie de aceasta functionalitate, dar ce mi se pare interesant la ea este ca putem seta ca executia codului sa se continue, dupa ce s-a executat actiunea custom din macro sau s-a afisat mesajul nostru, Un macro destul de interesant pe care l-am vazut in schimb era generarea automata a unui fisier de dump de fiecare data cand breakpointul era lovit.
Fiecarui breakpoint ii pot sa fie atasate unul sau mai multe label-uri. Acestea ne pot ajuta sa grupa breakpoint-urile in functie de anumite date. Pentru a putea vedea toate breakpoint-urile dintr-un proiect este nevoie sa deschidem fereastra "Breakpoints" din meniul "Debug->Windows->Breakspoints" sau folosind scurtatura "Ctrl+Alt+B". In aceasta lista putem in orice moment sa activam/ dezactivam un breakpoint, putem sa cautam un anumit breakpoint. Cea mai interesanta functionalitate mi se pare cea de import si export. Putem sa exportam o lista de breakpoint-uri pe care apoi o putem importa pe un alt calculator sau sa o folosim mai tarziu. Aceasta lista se salveaza sub forma unui fisier XML.
Cand suntem intr-un anumit breakpoint, fereastra "Imediate Windows" este extrem de utila pentru a putea executa cod scris la runtime. Trebuie sa avem grija ca nu putem sa scriem lambda expressions si sa le executam la runtime.
In mod normal cand suntem in debug, aplicatia noastra nu o sa se opreasca cand se arunca excepții care sunt mai tarziu prinse de catre codul nostru. Sunt insa cazuri cand vrem sa prindem si acest gen de exceptii. Pentru acest lucru avem la dispozitie fereastra "Exceptions" din "Debug->Exceptions" sau scurtatura "Ctrl+Alt+E". Putem selecta ca la anumite exceptii codul scris de noi sa se opreasca. In exemplul de mai jos pentru orice exceptie de tip AccessViolationException aruncata, care chiar daca exceptia este prinsa de sistemul nostru, aplicatie se opreste si putem face debug cand aceasta este aruncata.
Nu uitati ca in aceasta fereastra aveti disponibila funcionalitatea de cautare by name a unui excepti. Aceasta este extrem de utila cand vrem sa setam un comportament custom pentru o anumita exceptie, deoarece numarul acestora este foarte mare.
In momentul in care aplicatia noastra se afla intr-un anumit breakpoint, avem la dispozitie call stack-ul pentru a putea sa vedem de unde a fost apelat codul nostru. Folosind call stack-ul ne putem plimba pe acesta si sa vedem valoarea variabilelor din fiecare locatie. In fereastra "Locals" se pot observa toate variabilele locale, in functie de unde o sa fim pe stack o sa putem vedea variabilele pentru locatia respectiva din stack.
Fereastra "Autos" uneori poate sa fie extrem de utila, dar trebuie sa intelegem foarte bine ce afiseaza aceasta. In cadrul acestei ferestru o sa fie afisate variabilele, expresiile sau parametri care s-au modificat recent si pe care sistemul considera ca sunt relevanti. In cadrul ferestrei de "Watch" putem sa afisam orice expresie si sa urmarim cum se schimba aceasta valoare in timp ce face debug.
Pentru orice variabila, in debug, putem sa vedeam valoare acesteia, sa adaugam sau sa modificam aceasta valoare.
Cam atata ar fi despre base debugging stuff in Visual Studio. In urmatorul post de maine o sa vorbim despre multi-thread debugging, iar apoi despre Debugger Canvas.

Comments

  1. Si lista de shortcut-uri: http://msdn.microsoft.com/en-us/library/ms366733(v=vs.90) ;)

    ReplyDelete

Post a Comment

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine: threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration: TeamCity .NET 4.51 EF 6.0.2 VS2013 It see

Navigating Cloud Strategy after Azure Central US Region Outage

 Looking back, July 19, 2024, was challenging for customers using Microsoft Azure or Windows machines. Two major outages affected customers using CrowdStrike Falcon or Microsoft Azure computation resources in the Central US. These two outages affected many people and put many businesses on pause for a few hours or even days. The overlap of these two issues was a nightmare for travellers. In addition to blue screens in the airport terminals, they could not get additional information from the airport website, airline personnel, or the support line because they were affected by the outage in the Central US region or the CrowdStrike outage.   But what happened in reality? A faulty CrowdStrike update affected Windows computers globally, from airports and healthcare to small businesses, affecting over 8.5m computers. Even if the Falson Sensor software defect was identified and a fix deployed shortly after, the recovery took longer. In parallel with CrowdStrike, Microsoft provided a too