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

How to check in AngularJS if a service was register or not

There are cases when you need to check in a service or a controller was register in AngularJS.
For example a valid use case is when you have the same implementation running on multiple application. In this case, you may want to intercept the HTTP provider and add a custom step there. This step don’t needs to run on all the application, only in the one where the service exist and register.
A solution for this case would be to have a flag in the configuration that specify this. In the core you would have an IF that would check the value of this flag.
Another solution is to check if a specific service was register in AngularJS or not. If the service was register that you would execute your own logic.
To check if a service was register or not in AngularJS container you need to call the ‘has’ method of ‘inhector’. It will return TRUE if the service was register.
if ($injector.has('httpInterceptorService')) { $httpProvider.interceptors.push('httpInterceptorService&#…

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.51EF 6.0.2VS2013
It seems that there …

Run native .NET application in Docker (.NET Framework 4.6.2)

Scope
The main scope of this post is to see how we can run a legacy application written in .NET Framework in Docker.

Context
First of all, let’s define what is a legacy application in our context. By a legacy application we understand an application that runs .NET Framework 3.5 or higher in a production environment where we don’t have any more the people or documentation that would help us to understand what is happening behind the scene.
In this scenarios, you might want to migrate the current solution from a standard environment to Docker. There are many advantages for such a migration, like:

Continuous DeploymentTestingIsolationSecurity at container levelVersioning ControlEnvironment Standardization
Until now, we didn’t had the possibility to run a .NET application in Docker. With .NET Core, there was support for .NET Core in Docker, but migration from a full .NET framework to .NET Core can be costly and even impossible. Not only because of lack of features, but also because once you…