Tipps und Tricks zum Visual Studio-Debugger für .NET

70

Ich habe jahrelang mit dem Debugger von VS gearbeitet, aber hin und wieder stoße ich auf eine Funktion, die ich noch nie bemerkt habe, und denke: "Verdammt! Wie hätte ich das übersehen können? Es ist so nützlich!"

[Haftungsausschluss: Diese Tipps funktionieren in VS 2005 in einem C # -Projekt, keine Garantie für ältere Inkarnationen von VS oder anderen Sprachen]

Verfolgen Sie Objektinstanzen

Arbeiten mit mehreren Instanzen einer bestimmten Klasse? Wie kannst du sie auseinanderhalten? In den Programmiertagen vor der Speicherbereinigung war es einfach, Referenzen zu verfolgen - sehen Sie sich nur die Speicheradresse an. Mit .NET können Sie das nicht tun - Objekte können verschoben werden. Glücklicherweise können Sie in der Uhrenansicht mit der rechten Maustaste auf eine Uhr klicken und "Objekt-ID erstellen" auswählen.

Uhrenansicht http://img403.imageshack.us/img403/461/52518188cq3.jpg

Dadurch wird nach dem Wert der Instanz ein {1 #}, {2 #} usw. angehängt, wodurch der Instanz effektiv eine eindeutige Bezeichnung zugewiesen wird. Es sieht aus wie das:

nummerierte Instanz http://img383.imageshack.us/img383/7351/11732685bl8.jpg

Die Beschriftung bleibt für die Lebensdauer dieses Objekts erhalten.

Aussagekräftige Werte für beobachtete Variablen

Standardmäßig ist der Wert einer überwachten Variablen der Typ. Wenn Sie seine Felder sehen möchten, müssen Sie es erweitern, und dies kann lange dauern (oder sogar eine Zeitüberschreitung!), Wenn es viele Felder gibt oder sie etwas Kompliziertes tun.

Einige vordefinierte Typen zeigen jedoch aussagekräftigere Informationen:

  • Zeichenfolgen zeigen ihren tatsächlichen Inhalt
  • Listen und Wörterbücher zeigen die Anzahl ihrer Elemente usw.

aussagekräftige Informationen http://img205.imageshack.us/img205/4808/37220487md1.jpg

Wäre es nicht schön, das für meine eigenen Typen zu haben?

Hmm ...

... einige Zeit mit .NET Reflector zeigt, wie einfach dies mit dem DebuggerDisplayAttribut meines benutzerdefinierten Typs erreicht werden kann:

[System.Diagnostics.DebuggerDisplay("Employee: '{Name}'")]
public class Employee {
    public string Name { get { ... } }
    ...
}

... erneut ausführen und ...

ta da! http://img60.imageshack.us/img60/926/79816018ha1.jpg

Hier gibt es viel mehr Infos zu diesem Thema: MSDN

Unterbrechen Sie alle Ausnahmen

... auch diejenigen, die im Code behandelt werden! Ich weiß, ich bin so ein N00B, weil ich seit meiner Geburt nichts davon weiß, aber hier geht es trotzdem - vielleicht hilft das irgendwann jemandem:

Sie können einen debuggten Prozess zwingen, jedes Mal, wenn eine Ausnahme ausgelöst wird, in den Debug-Modus zu wechseln. Haben Sie schon einmal stundenlang auf Fehlersuche gegangen, um auf einen solchen Code zu stoßen?

try {
    runStrangeContraption();
} catch(Exception ex) {
    /* TODO: Will handle this error later */
}

In diesen Fällen ist es sehr praktisch, alle Ausnahmen zu erfassen. Dies kann über Debug> Ausnahmen ... (Strg-Alt-E) aktiviert werden . Aktivieren Sie die Kontrollkästchen in der Spalte "Ausgelöst" für jede Art von Ausnahme, die Sie benötigen.


Das waren ein paar Momente, in denen ich mir die Stirn schlug. Möchten Sie Ihre teilen?

Cristian Diaconescu
quelle
Dies ist eher eine Notiz an sich selbst als eine Frage, aber vielleicht finden es andere nützlich. Hoffentlich lerne ich auch etwas Neues.
Cristian Diaconescu

Antworten:

7

Zwei In-Code-Tricks:

Das System.Diagnostics.DebuggerStepThrough- Attribut gefällt mir sehr gut . Sie können es an eine Klasse, Methode oder Eigenschaft anhängen, damit VS beim Debuggen nicht standardmäßig den Code eingibt. Ich bevorzuge es gegenüber dem DebuggerHidden- Attribut, da Sie trotzdem Haltepunkte in den ignorierten Code einfügen können, wenn Sie ihn wirklich debuggen müssen.

Ein weiterer (manchmal) nützlicher Aufruf ist System.Diagnostics.Debugger.Launch () ; Wenn die Ausführung darauf trifft, wird das Dialogfeld "Debugger auswählen" angezeigt, und ein Debugger wird gestartet. Ein bisschen unhöflich, aber nützlich, wenn es besonders unangenehm ist, Prozesse anzuhängen, wie ein Prozess, der von einem anderen erzeugt wird und Ihren Code sofort ausführt.

Paolo Tedesco
quelle
2
Ich habe kürzlich etwas über System.Diagnostics.DebuggerStepThrough gelernt - nützlich. Es kommt auch vor, dass ich Debugger.Launch in den letzten Wochen häufig verwendet habe. Wenn ich für ein bestimmtes Projekt versuche, direkt über das Dialogfeld "An Prozess anhängen" anzuhängen, stirbt der Prozess einfach ab, verwendet jedoch Debugger.Launch () hängt den (gleichen?!) Debugger ein.
Cristian Diaconescu
19
try {
    // do something big
}
catch {
    // breakpoint set here:
    throw CantHappenException("something horrible happened that should never happen.");
}

Wie sehen Sie die Ausnahme, die ursprünglich ausgelöst wurde? Geben Sie in einem Überwachungsfenster $ exception ein

Sockel
quelle
1
JA WIRKLICH? Süss! Das ist wahnsinnig nützlich. Besonders wenn Sie an einem schlecht geschriebenen Projekt arbeiten.
EightyOne Unite
17

Hier ist ein weiterer netter Trick, den ich gelernt habe:

System.Diagnostics.Debugger.Break()

Programmiert wird der Debugger bei der nächsten Anweisung unterbrochen. Der wirklich schöne Teil ist, dass dies auch für ein Programm funktioniert, das im Release- Modus kompiliert wurde , ohne Informationen zu debuggen.

Cristian Diaconescu
quelle
7
Ich bevorzuge es, das mit If (System.Diagnostics.Debugger.IsAttached) {System.Diagnostics.Debugger.Break ()} zu umgeben. Andernfalls können Clients böse Fehler bekommen, wenn dies nicht entfernt wird!
Gavin Miller
12

Ich stelle immer sicher, dass die Eigenschaft "Name" für neue Threads festgelegt wird, die ich erstelle. Auf diese Weise kann ich beim Debuggen verschiedene Threads leichter identifizieren.

Jon Tackabury
quelle
7

Ein paar von mir

  • Deaktivieren Sie die Option "Nur meinen Code aktivieren" unter Extras-> Optionen-> Debuggen.
  • Bedingte Haltepunkte - sie retten mir fast jeden Tag das Leben
  • Verwenden Sie die .NET Framework-Quelle, wenn die Dinge hässlich werden
Atanas Korchev
quelle
6

.load sos im Sofortfenster :)

Leppie
quelle
1
Was ist zu erklären? Es gibt unzählige Seiten im Internet, die erklären, wie man SOS benutzt.
Leppie
4

Tools -> An Prozess anhängen - leicht zu vergessen, aber damit kann ich Skripte auf Webseiten debuggen, verwalteten Code, der in einem anderen Prozess geladen wurde (denken Sie an ein Add-In-Modell), oder sogar nicht verwalteten Code. Achten Sie darauf, dass automatisch die Art des Debuggens ausgewählt wird, an der Sie interessiert sind.

Tracepoints (und andere Haltepunktfunktionen ... klicken Sie mit der rechten Maustaste auf den Haltepunkt und haben Sie Spaß)! - http://blogs.msdn.com/saraford/archive/2008/06/13/did-you-know-you-can-use-tracepoints-to-log-printf-or-console-writeline-info-without -editing-your-code-237.aspx

Das unmittelbare Fenster ist fantastisch.

Remote-Debugging ist sehr nützlich, wenn Sie Apps bereitstellen (und auf den Computer gelangen können, auf dem das Problem reproduziert werden kann).

Es gibt Tonnen mehr. Versuchen Sie, in WinDbg und SoS einzusteigen!

David Mohundro
quelle
Leider habe ich gerade erfahren, dass diese für die Express Edition nicht funktionieren.
Michael Haren
4

Ich fand das Modulfenster oft nützlich. Es zeigt an, ob der Debugger eine erforderliche DLL geladen hat und welche Version der DLL geladen ist. Außerdem können Sie eine DLL manuell laden oder entladen.

Etsuba
quelle
3

Bedingte Unterbrechungen sind sehr nützlich, wenn Sie Code haben, der häufig wiederholt wird, aber nur unter bestimmten Bedingungen fehlschlägt, z. B. Code in einer Schleife, Methoden, die von einer Schleife aufgerufen werden, oder Methoden, die von mehreren Threads aufgerufen werden. Setzen Sie die break-Anweisung in die interessierende Zeile und stellen Sie die Bedingungen so ein, dass sie dem Fehlerfall entsprechen. (Es gibt ein kurzes Beispiel hier .)

ARKBAN
quelle
2

Zwei von mir: eine, von der ich hoffe, dass sie jeder überall nutzt:

Debug.Assert(<condition>, <message>)

der zweite DebuggerHidden:

<DebuggerHidden()> _
Public Sub ReadDocumentProperty(ByVal propertyName As String, ByRef PropVal As Integer, ByVal DefaultVal As Integer)
    Try
        Dim prop As Office.DocumentProperty
        prop = CustomProps.Item(propertyName)
        PropVal = CType(prop.Value, Integer)
    Catch
        PropVal = DefaultVal
    End Try
End Sub

Selbst wenn Sie Debug, Ausnahmen, Unterbrechung bei ausgelösten Ausnahmen festgelegt haben, werden Ausnahmen hier nicht abgefangen.

CestLaGalere
quelle
1

Erstellen Sie ein Makro zum Anhängen an einen Prozess und weisen Sie es einer nicht verwendeten Tastenkombination zu. Viel schneller als es geht: Debuggen -> An Prozess anhängen -> Prozess in der Prozessliste suchen -> ...

Tony_Henrich
quelle
2
Strg-Sh-P für "An Prozess anhängen". Sie müssen jedoch immer noch nach dem Prozessnamen suchen und suchen ...
Cristian Diaconescu
1

Wie wäre es, wenn Sie die IDE so einstellen, dass sie in Ausnahmen zerfällt, wenn sie auftreten, auch wenn kein Debugpunkt festgelegt ist.

Debug -> Ausnahmen -> Commmon Language Runtime Exceptions -> Thrown

Dies macht das Auffinden versteckter Probleme bei der Ausnahmebehandlung zum Kinderspiel. Tatsächlich ist dies eine Art Einstellung, die jeder Entwickler während der gesamten Entwicklung festgelegt haben sollte, um unbehandelte oder sogar behandelte Ausnahmen zu vermeiden, die darunter liegen.

Chathuranga Wijeratna
quelle
Sehr nützlich, kann aber von Entwicklern ruiniert werden, die sich auf Ausnahmen für den "normalen" Codefluss verlassen. In dem großen Projekt, an dem ich arbeite, gibt es mehr als eine Handvoll Ausnahmen, die "beiläufig" ausgelöst und abgefangen werden, genau in der Zeit, die das Programm für die Initialisierung benötigt. Normalerweise starte ich den Prozess, warte auf die Initialisierung und aktiviere erst dann "Pause bei ausgelösten Ausnahmen".
Cristian Diaconescu
0

In nicht verwaltetem Code können Sie "Daten-Haltepunkte" festlegen. Sie verwenden die Debug-Register der CPU, um ein INT3 auszugeben, und der Debugger stoppt diesen Befehl ohne Overhead zur Laufzeit (in einer älteren Version hat der Debugger das Programm durchlaufen und den Speicher überprüft ..... langsam!).

Dies ist nützlich, wenn an einer bekannten Adresse eine Beschädigung vorliegt (Stack / Heap kann möglicherweise überlastet werden).

Auch AutoExp.dat in ide \ packages \ debugger kann angepasst werden, um Ihre Datenstrukturen anzuzeigen.

Zeiger, mb zeigt einen Hex-Dump im Überwachungsfenster http://msdn.microsoft.com/en-us/magazine/dd252945.aspx

Yum!

Dominik Weber
quelle