Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 9 Code erstellen und debuggen
Pfeil 9.1 Ausnahmen
Pfeil 9.1.1 Methodenaufrufe
Pfeil 9.1.2 Hierarchie der Ausnahmen
Pfeil 9.1.3 Eigene Ausnahmen
Pfeil 9.2 Protokollierung
Pfeil 9.2.1 Ausgabe mit Debug
Pfeil 9.2.2 Ausgabe mit Trace
Pfeil 9.2.3 Ausgabeziel mit TraceListener
Pfeil 9.2.4 Steuerung mit Konfigurationsdateien
Pfeil 9.3 Visual Studio Debugger
Pfeil 9.3.1 Debuggen im Haltemodus
Pfeil 9.3.2 Fenster zum Zugriff auf Variablen
Pfeil 9.4 Unit Tests
Pfeil 9.5 Refactoring
Pfeil 9.6 UML
Pfeil 9.6.1 Klassendiagramm
Pfeil 9.6.2 Toolbox
Pfeil 9.6.3 Das Fenster Klassendetails
Pfeil 9.6.4 Klassendiagramme als Bilder exportieren
Pfeil 9.7 Codeausschnitte (Code Snippets)
Pfeil 9.7.1 Anatomie
Pfeil 9.7.2 Eigene Codeausschnitte


Rheinwerk Computing - Zum Seitenanfang

9.2 Protokollierung Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn ein Fehler nicht zu einer Ausnahme führt, ist er viel schwerer aufzuspüren. Dann bleibt nichts anderes als eine Analyse des Programmlaufes. Die meiste Zeit bei der Fehlersuche verbringt man mit der Suche nach der Stelle, die den Fehler ausgelöst hat. Hier können selbst definierte Ausgaben sehr viel helfen. Sie haben den Nachteil, nicht so »komfortabel« wie ein grafischer Debugger zu sein. Andererseits haben sie ein paar unschätzbare Vorteile:

  • Sie bestimmen die ausgedruckte Information.
  • Sie beeinflussen den Programmlauf nur minimal. (Das ist hilfreich bei zeitkritischen und nebenläufigen Anwendungen, in denen mehrere Threads gleichzeitig laufen.)
  • Sie brauchen keinen Debugger. (Das ist hilfreich zur Fehlersuche bei einem Kunden.)
  • Wenn sie entsprechend konfiguriert sind, können sie selbst bei Programmen helfen, die einen Debugger zum Absturz bringen.
  • Auch andere Ausgaben können speziell protokolliert werden, die mit der eigentlichen Programmlogik nichts zu tun haben (zum Beispiel Dateizugriffe).

Rheinwerk Computing - Zum Seitenanfang

9.2.1 Ausgabe mit Debug Zur nächsten ÜberschriftZur vorigen Überschrift

Die einfachste Art, Informationen auszudrucken, ist die Methode Console.WriteLine. Sie hat den Nachteil, dass Fehlerausgaben von normalen Ausgaben nicht getrennt sind. Außerdem müssen sie manuell vor Auslieferung der Software gelöscht werden. Daher bietet uns .NET die Klasse Debug im Namensraum System.Diagnostics an, mit der wir Ausgaben an einen eigenen Ausgabekanal schicken können. Standardmäßig ist das das Fenster Ausgabe in Visual Studio, das auch während der Kompilierung benutzt wird. Sie können es sich anzeigen lassen, indem Sie im Menü Ansicht das Untermenü Andere FensterAusgabe wählen.

Protokoll anzeigen

Analog zur Klasse Console schreiben Sie mit Debug.Write eine Ausgabe, allerdings mit etwas weniger Überladungen. Die folgende Syntax zeigt alle Methoden zur Erzeugung einer unbedingten Ausgabe. Es fehlt insbesondere eine formatierte Ausgabe. Sie müssen die Ausgabe also selbst zu einer Zeichenkette zusammensetzen. Die Zeichenkette kategorie wird dem wert vorangestellt:


Public Shared Sub Ausgabe(wert As Art) 
Public Shared Sub Ausgabe(wert As Art, kategorie As String)

Ausgabe: Write oder WriteLine, Art: String oder Object

Analog zu diesen Ausgabemethoden gibt es Varianten, die nur dann eine Ausgabe machen, wenn die im ersten Parameter angegebene Bedingung erfüllt ist:


Public Shared Sub AusgabeIf(bedingung As Boolean, wert As Art) 
Public Shared Sub AusgabeIf(bedingung As Boolean, wert As Art, _ 
                            kategorie As String)

Ausgabe: Write oder WriteLine, Art: String oder Object

Im folgenden Beispiel wird bei jedem größeren Wert mit WriteLineIf eine Ausgabe im Ausgabe-Fenster produziert:


'...\Lauf\Protokollierung\Eingrenzung.vb

Option Strict On 
Namespace Lauf 
  Module Eingrenzung 
    Private rnd As New Random(1234) 
    Sub Ausgeben(ByRef wert As Integer, ByVal i As Integer) 
      Dim aus As Integer = rnd.Next(0, 7) 
      wert += aus 
      Debug.WriteLineIf(aus > 4, _ 
                    i & ": wieder eine Fünfer weg: " & wert, "Geld") 
    End Sub

    Sub Test() 
      Dim wert As Integer 
      For i As Integer = 0 To 10 
        Ausgeben(wert, i) 
      Next 
      Console.WriteLine("Gesamtausgabe: {0}", wert) 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Die normale Ausgabe ist sehr kurz:

Gesamtausgabe: 40

Das Ausgabe-Fenster enthält nur die Ausgaben von Debug (siehe Abbildung 9.1). Der Kategorieparameter Geld steht vor den eigentlichen Ausgaben.

Abbildung 9.1 Ausgabe von »Debug.WriteLineIf«


Hinweis
Sollten Sie im Ausgabe-Fenster nichts sehen, prüfen Sie in den Optionen des Debuggers (Menü Extras • Optionen), ob die Ausgabe in das Direktfenster umgeleitet wird.


Einrücken der Ausgabe

Mit der Methode Indent wird die Einzugsebene um eins erhöht, mit Unindent wird sie um eins verringert. Mit der Eigenschaft IndentSize bestimmen Sie die Einheit. Standardmäßig sind es vier Leerzeichen. IndentLevel legt eine Einzugsebene direkt fest (ersetzt Indent-Aufrufe).

Debug.WriteLine("Ausgabe 1") 
Debug.Indent() 
Debug.WriteLine("Ausgabe 2") 
Debug.IndentLevel = 3 
Debug.WriteLine("Ausgabe 3") 
Debug.Unindent() 
Debug.WriteLine("Ausgabe 4") 
Debug.IndentSize = 2 
Debug.IndentLevel = 1 
Debug.WriteLine("Ausgabe 5")

Der Code führt zu folgender Ausgabe:

Ausgabe 1 
    Ausgabe 2 
            Ausgabe 3 
        Ausgabe 4 
  Ausgabe 5

Prüfung mit Assert

Sie sollten die Methode Assert einsetzen, um Annahmen zu prüfen, von denen Sie eigentlich meinen, dass sie immer erfüllt sind. Die Methode ist also zur Erkennung schwerwiegender Fehler gedacht. Die Methode zeigt eine Fehlermeldung an, wenn ein Ausdruck mit False ausgewertet wird.

Debug.Assert(wert >= 0, "Negativer Wert")

Ist wert negativ, erscheint die Nachricht aus Abbildung 9.2.

Abbildung 9.2 Meldung der Methode »Debug.Assert«

Das Dialogfenster enthält neben der Zeichenfolge des zweiten Parameters auch Informationen darüber, in welcher Klasse und welcher Methode der Assertionsfehler aufgetreten ist.


Rheinwerk Computing - Zum Seitenanfang

9.2.2 Ausgabe mit Trace Zur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse Trace hat die gleiche Funktionalität wie Debug. Ein Unterschied macht sich bei einem Wechsel der Build-Konfiguration zwischen Release und Debug bemerkbar (siehe Abbildung 9.3).

Abbildung 9.3 Debug/Release-Build-Konfiguration

Mit der Standardeinstellung Debug erzeugen Debug und Trace Ausgaben, während bei Release Aufrufe von Debug ignoriert werden. Dies liegt daran, dass im zweiten Fall die Aufrufe gar nicht kompiliert werden und die Anwendung nicht aufblähen. Der Hintergrund ist das in Abschnitt 4.8.1, »Beispiel: Bedingte Kompilierung«, beschriebene Attribut.

Unterhalb des Verzeichnisses der Quellcodedateien legt die Entwicklungsumgebung das Verzeichnis \bin an, das – je nach eingestellter Build-Konfiguration – die beiden Verzeichnisse \Debug und \Release enthält und das entsprechende Kompilat aufnimmt. Die PDB-Dateien in diesen Verzeichnissen ermöglichen dem Debugger eine für Menschen lesbare Ausgabe.


Rheinwerk Computing - Zum Seitenanfang

9.2.3 Ausgabeziel mit TraceListener Zur nächsten ÜberschriftZur vorigen Überschrift

Im Namensraum System.Diagnostics sind fünf Listener als Ziel der Protokollierung definiert, die alle aus der abstrakten Klasse TraceListener abgeleitet sind (siehe Tabelle 9.2):


Tabelle 9.2 Einige Listener-Klassen des Namensraums »System.Diagnostics«

Listener-Klasse Ziel der Ausgabe

ConsoleTraceListener

Konsole

DefaultTraceListener

Entwicklungsumgebung (Standardeinstellung)

EventLogTraceListener

Windows-Ereignisprotokoll

TextWriterTraceListener

Stream, Textwriter oder Datei (siehe Kapitel 7, »Eingabe und Ausgabe«)


Die folgende Klassenhierarchie zeigt die von TraceListener abgeleiteten Klassen in .NET.

System.Object 
 +System.MarshalByRefObject 
   +2--TraceListener 
        +1--FileLogTraceListener 
        +2-+DefaultTraceListener 
        |  +EventLogTraceListener 
        |  +TextWriterTraceListener 
        |    +2-+ConsoleTraceListener 
        |       +DelimitedListTraceListener 
        |       +EventSchemaTraceListener 
        |       +XmlWriterTraceListener 
        +3--EventProviderTraceListener 
        +4-+IisTraceListener 
           +WebPageTraceListener

  1: Microsoft.VisualBasic.Logging 
  2: System.Diagnostics 
  3: System.Diagnostics.Eventing 
  4: System.Web

Die Ausgabeziele von Debug und Trace sind in deren Eigenschaft Listeners vom Auflistungstyp TraceListenerCollection gespeichert. Sie können mit Add, Remove, Clear usw. die Liste nach Bedarf anpassen. Beachten Sie, dass die Eigenschaft Listeners beider Klassen dieselbe Auflistung bezeichnet. Im folgenden Codefragment wird die Liste geleert und dann die Konsole als einziges Ausgabeziel hinzugefügt. Debug und Trace schreiben damit nur noch in die Konsole.

Debug.Listeners.Clear() 
TextWriterTraceListener console = new TextWriterTraceListener(Console.Out) 
Debug.Listeners.Add(console)

Dateiausgabe mit TextWriterTraceListener

Mit diesem Listener leiten Sie einfach Ausgaben in eine Datei um. Übergeben Sie dem Konstruktor einen Dateipfad, werden die Ausgaben an die (gegebenenfalls neu erstellte) Datei angehängt. Brauchen Sie mehr Kontrolle, verwenden Sie einen anderen Konstruktor. Im folgenden Codefragment stellt Flush sicher, dass vor dem Schließen der Ausgabepuffer geleert wird. Alternativ setzen Sie AutoFlush=True. Da Debug und Trace dieselben Listener verwenden, werden zwei Zeilen in die angegebene Datei geschrieben.

Dim listener As New TextWriterTraceListener("C:\DebugProtocol.txt") 
Trace.Listeners.Add(listener) 
Debug.WriteLine("Debug.WriteLine-Anweisung") 
Trace.WriteLine("Trace.WriteLine-Anweisung") 
listener.Flush() 
listener.Close()

Das folgende Beispiel zeigt, wie mithilfe dieses Mechanismus datierte Fehlerinformationen auch über das Ende einer Anwendung hinaus gerettet werden können:


'...\Lauf\Protokollierung\PostMortem.vb

Option Strict On 
Namespace Lauf 
  Module PostMortem 
    Sub Test() 
      Debug.Listeners.Clear() 
      Dim tl = New TextWriterTraceListener("C:\Temp\ErrorProtocol.txt") 
      Debug.Listeners.Add(tl) 
      Debug.AutoFlush = True 
      Try 
        Operation() 
      Catch ex As Exception 
        Trace.WriteLine("Fehler: " & Now & " – " & ex.Message) 
      Finally 
        tl.Close() 
      End Try 
    End Sub

    Sub Operation() 
      Throw New Exception("Werch ein Illtum.") 
    End Sub 
  End Module 
End Namespace

Der Inhalt der Datei zeigt die Protokollierung der Ausnahme:

Fehler: 20.12.2008 20:52:02 – Werch ein Illtum.

Mehrere Listener verwalten

Debug und Trace schreiben in alle in Listeners gespeicherten Ausgabeziele. Um die Ziele zu beschränken, müssen die entsprechenden Listener (temporär) aus der Liste entfernt werden. Sie können leichter gefunden werden, wenn ihnen mit einem zweiten Konstruktorparameter ein Name gegeben wird.

Im folgenden Beispiel werden zwei benannte Listener registriert und es wird eine Meldung geschrieben. Anschließend wird ein Listener aus der TraceListenerCollection gelöscht. Die anschließende Meldung wird nur vom verbleibenden Listener weitergeleitet.

Dim ZielA As TextWriterTraceListener("C:\A.txt", "AL") 
Trace.Listeners.Add(ZielA) 
Dim ZielB As TextWriterTraceListener("C:\B.txt", "BL") 
Trace.Listeners.Add(ZielB) 
Trace.AutoFlush = True

Trace.WriteLine("Erste Information") 
Trace.Listeners.Remove("BL") 
Trace.WriteLine("Zweite Information")

Nutzen Sie statt AutoFlush die Methode Flush, muss sie vor der Deregistrierung aufgerufen werden.

Ereignisprotokollausgabe

Mit dem Ziel EventLogTraceListener schreiben Sie in das Windows-Ereignisprotokoll.


Public Sub New() 
Public Sub New(eventLog As EventLog) 
Public Sub New(source As String)

Im folgenden Codefragment wird ein Ereignisprotokoll namens MyProtocol auf der lokalen Maschine eingerichtet, die durch einen Punkt benannt ist. Mit der Eigenschaft Source geben Sie einen Bezeichner für die Ereignisquelle an. Innerhalb der Ereignisprotokolle von Windows muss dieser eindeutig sein. EventLog.GetEventLogs(".") listet alle bekannten Ereignisprotokolle auf. Windows definiert bereits Application, System und Security.

Dim log As New EventLog("MyProtocol", ".") 
log.Source = "MyApplication" 
Dim el New EventLogTraceListener(log) 
Debug.Listeners.Add(el) 
Debug.WriteLine("Ein Eintrag im Ereignisprotokoll") 
el.Flush()

Ereignisprotokolle sollten nur für wenige, besonders wichtige Meldungen verwendet werden.


Rheinwerk Computing - Zum Seitenanfang

9.2.4 Steuerung mit Konfigurationsdateien topZur vorigen Überschrift

Die Methoden WriteIf und WriteLineIf erlauben die bedingte Protokollierung. Die im ersten Parameter angegebene Bedingung ist der Schlüssel zur Steuerung. Normalerweise wird sie durch Code gesetzt. Wenn Sie eine von System.Diagnostics.Switch abgeleitete Klasse verwenden, können Sie die Bedingung in einer Konfigurationsdatei steuern.

Object 
 +Switch 
   ++BooleanSwitch 
    +SourceSwitch 
    +TraceSwitch

BooleanSwitch

Dieser Schalter kennt nur die Stellungen An und Aus. Dem Konstruktor übergeben Sie den Namen des Schalters und eine Beschreibung:

Dim meiner As New BooleanSwitch("MeinSchalter", "Ablaufverfolgung in MyApp")

Der Schalter startet in der Stellung False und kann mit meiner.Enabled = True angeschaltet werden. Diese Eigenschaft wird auch in den Protokollfunktionen verwendet.

Trace.WriteLineIf(meiner.Enabled, "Ablaufverfolgung:" & Now.ToString())

Die Schalterstellung können Sie auch in der Anwendungskonfigurationsdatei festlegen:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
   <system.diagnostics> 
      <switches> 
         <add name="MeinSchalter" value="1" /> 
      </switches> 
   </system.diagnostics> 
</configuration>

Jeder Schalter wird in einem eigenen add-Element dem switches-Knoten hinzugefügt. Das Attribut name gibt den Namen des Schalters an und das Attribut value die Schalterstellung. Dabei steht 1 für True und 0 für False. Beim Start der Anwendung wird die Konfigurationsdatei eingelesen und schafft eine Vorbelegung des Schalters, die im Code geändert werden kann. Durch Änderung der XML-Datei vor dem Programmstart wird die Anwendung gesteuert.

TraceSwitch

Dieser Schalter kennt nicht nur die Stellungen An und Aus, sondern verschiedene Einstellungen, die über die Eigenschaft Level gesetzt werden.


Public Property Level As TraceLevel

Die Eigenschaft ist vom Typ der Enumeration TraceLevel (siehe Tabelle 9.3). Jeder Wert, bis auf Off, umfasst die niederwertigeren. Wenn zum Beispiel Info gesetzt ist, dann sind damit automatisch auch Error und Warning gesetzt.


Tabelle 9.3 Die Enumeration »TraceLevel«

Konstante Wert Art der ausgegebenen Meldungen

Off

0

Keine

Error

1

Fehlermeldungen

Warning

2

Fehler- und Warnmeldungen

Info

3

Fehler-, Warn- und Informationsmeldungen

Verbose

4

Alle Meldungen


Der TraceSwitch-Konstruktor bekommt einen Namen und eine Beschreibung übergeben.

Dim meiner As New TraceSwitch("MeinSchalter", "Ablaufverfolgung in MyApp") 
meiner.Level = TraceLevel.Warning

Die Methoden WriteIf und WriteLineIf brauchen im ersten Parameter einen booleschen Wert. Daher definiert TraceSwitch die booleschen Eigenschaften TraceError, TraceWarning, TraceInfo und TraceVerbose.

Trace.WriteLineIf(meiner.TraceWarning, "Ablaufverfolgung:" & Now.ToString())

Analog zu BooleanSwitch kann ein Schalter in einer Konfigurationsdatei definiert und vorbelegt werden – im folgenden Beispiel mit TraceLevel.Info:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
   <system.diagnostics> 
      <switches> 
         <add name="MeinSchalter" value="3" /> 
      </switches> 
   </system.diagnostics> 
</configuration>


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual Basic 2008
Visual Basic 2008
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Visual Basic 2012






 Visual Basic 2012


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de