2009. március 12., csütörtök

System.Diagnostics.Debugger

A System.Diagnostics névtérben van egy osztály, a Debugger, aminek a segítségével a - micsoda meglepetés - debuggerrel kommunikálhatunk. A Break() metódus segítségével például "programozottan" helyezhetünk el breakpointokat a kódunkban.
Ha a programunk úgy fut, hogy a debugger már rá van akasztva - tehát F5-tel indítottuk a Studióból, vagy utólag ráakaszkodtunk a futó processzre -, a Debugger.Break() pont ugyanazt fogja csinálni, mint egy hagyományos breakpoint. Debugger nélkül (jellemzően: CTRL+F5) futtatva egy párbeszédablak fog figyelmeztetni, hogy egy user-defined breakpointhoz értünk, ami valószínűleg egy program error, és választhatunk a továbbfutás, vagy a debugolás között.

A bool Debugger.Launch() metódussal a debugger elindulását kényszeríthetjük ki: itt szintén egy párbeszédablak segítségével kell kiválasztani azt a debuggert (jellemzően CLR debuggert, már futó vagy új Visual Studio példányt), amit a hibát okozó processzhez csatolni szeretnénk. A metódus a visszatérési bool értékkel jelzi, hogy sikerült-e ez a művelet.
Az, hogy a debugger csatolva van-e már, a bool Debugger.IsAttached statikus property segítségével tudhatjuk meg.

Ennek a néhány low-level debugger API hívásnak a segítségével megkönnyíthetjuk az olyan jellegű hibáknak a felderítését, amikor valami elméletileg nem lehetséges ("ezt a metódust sose hívom null-lal!"), de a gyakorlat azt mutatja, hogy bizony mégis. Az alábbi példában, ha a paraméterként kapott id string null, megállunk, ha éppen úgy futtatjuk az alkalmazást, hogy debugolunk, egyébként pedig megdobjuk a kivételt (persze, ha a Break() után továbbmegyünk, akkor debug módban is megdobjuk, de ott már lehetőségünk van mindenféle aljasságra):

static bool IsValidId(string id)
{
    if (id == null)
    {
        if (Debugger.IsAttached)
            Debugger.Break();
        throw new ArgumentNullException("name", "Id cannot be null.");
    }
    return id.StartsWith("ID-") && id.Length == 10;
}

Elejét vehetjük annak a kínos szituációnak is, amikor egy breakpoint fölött vakarjuk a fejünket, idegesen húzkodva az egeret a változóink fölött, hogy ez most hogy a Jóistenbe', alattunk meg mellékbüntetésként eltimeoutol egy adatbázis- vagy webservice hívás:

SqlCommand command = new SqlCommand();
command.CommandTimeout = Debugger.IsAttached ? int.MaxValue : 30;

A [Conditional] attribútummal kidekorált metódusokkal kombinálva pedig ugyanabból a kódbázisból pedig könnyedén fordíthatunk produkciós és "debugger-indítós" verziókat.

0 megjegyzés:

Megjegyzés küldése