Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0142: Logger

 von 

Hinweis zum Tippvorschlag  

Dieser Vorschlag wurde noch nicht auf Sinn und Inhalt überprüft und die Zip-Datei wurde noch nicht auf schädlichen Inhalt hin untersucht.
Bitte haben Sie ein wenig Geduld, bis die Freigabe erfolgt.

Über den Tipp  

Dieser Tippvorschlag ist noch unbewertet.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Dateien und Laufwerke
  • Sonstiges

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
Logging, LogFile, My, ApplicationEvents, Exception, Ausnahmen

Der Vorschlag wurde erstellt am: 06.11.2007 23:13.
Die letzte Aktualisierung erfolgte am 05.02.2009 15:45.

Zurück zur Übersicht

Beschreibung  

Logger ist eine sehr einfache Klasse, mit der man komfortabel beliebige Meldungen in ein LogFile schreiben kann. Das LogFile wird ordentlich im Anwendungs-Daten-Verzeichnis plaziert (wie man es eigentlich machen sollte). Gezeigt wird auch, wie man anwendungsweit unbehandelte Ausnahmen loggen kann. Ein "Absturz" des Programms wird dadurch nicht unterdrückt, da m.E. i.A. der sofortige Abbruch die einzig verantwortliche Aktion ist, um die gravierenden Folgeschäden abzuwenden, die auftreten können, wenn ein Programm instabil weiterläuft.

Anmerkungen:
1) Dieses Beispiel funktioniert nur in Windows Applications, die als Einzelinstanz laufen (Letzteres kann man durch eine entsprechende Einstellung in den Projekteigenschaften erzwingen).
2) Es gibt (auch kostenlos) Tools, die flexibleres und leistungsfähigeres Logging bereitstellen.
3) Es gibt auch anspruchsvollere Logging-Konzepte, als dieses "Schreibe, wenn ich sage".

Schwierigkeitsgrad

Schwierigkeitsgrad 1

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [14,98 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' ------------ Anfang Projektgruppe ErrorLog.sln  ------------
' ----------- Anfang Projektdatei ErrorLog.vbproj  -----------
' ------------ Anfang Datei ApplicationEvents.vb  ------------
' IDE-Voreinstellungen:
' Option Strict On
' Option Explicit On

' Projekt-Voreinstellungen:
' Imports System.Windows.Forms
' Imports Microsoft.VisualBasic.ControlChars

Imports Microsoft.VisualBasic.ApplicationServices

Namespace My

    ' Diese nützliche Datei wird generiert und geöffnet, wenn man in den
    ' Anwendungseinstellungen auf "Anwendungsereignisse anzeigen" klickst

    Partial Friend Class MyApplication

        ' #Const HideErrLogDisplay = True '2 Möglichkeiten, UnhandledExceptions zu loggen

#If HideErrLogDisplay Then   ' Diese Variante behandelt UnhandledExceptions nur in
                                     ' der kompilierten Exe, läßt im DebugMode die IDE ihren
                                     ' Job tun

        Private Sub MyApplication_UnhandledException( _
                    ByVal sender As Object, _
                    ByVal e As UnhandledExceptionEventArgs) Handles Me.UnhandledException

            Logger.Entry(e.ExceptionObject).Add(Now).OpenLogFile()

        End Sub

#Else     ' Diese Variante zeigt das ErrorLogFile auch an, wenn in der IDE gedebugt wird

        Private Sub MyApplication_Startup(ByVal sender As Object, ByVal e As _
            StartupEventArgs) Handles Me.Startup

            AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf AD_UnhandledException

        End Sub

        Private Sub AD_UnhandledException( _
                    ByVal sender As Object, ByVal e As System.UnhandledExceptionEventArgs)

            Logger.Entry(e.ExceptionObject).Add(Now).OpenLogFile()

        End Sub

#End If

    End Class ' MyApplication

End Namespace ' My

' ------------- Ende Datei ApplicationEvents.vb  -------------
' --------------- Anfang Datei frmErrorLog.vb  ---------------
Public Class frmErrorLog

    Private Sub cmdLogText_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles cmdLogText.Click

        Logger.Entry("Hi!").Add("I am a Logging-Entry")

        ' andere Schreibweise mit selbem Ergebnis:
        ' Logger.Entry("Hi", Lf, "I am a Logging-Entry")
    End Sub

    Private Sub cmdLogWithTimestamp_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles cmdLogWithTimestamp.Click

        ' Timestamp anfügen ist so einfach, dass ich nicht mal eine extra Sub dafür spendiere
        Logger.Entry(Now).Add("Hi!").Add("I am a Logging-Entry with timestamp")

    End Sub

    Private Sub cmdLogException_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles cmdLogException.Click

        ' Beispiel, eine gefangene Exception zu loggen (mit Timestamp)
        Try

            Dim Lb As Label = DirectCast(sender, Label)

        Catch ex As Exception

            Logger.Entry(Now).Add(ex)

        End Try

    End Sub

    Private Sub cmdUnhandledException_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles cmdUnhandledException.Click

        ' Dieser Fehler wird in den globalen ApplicationEvents behandelt werden
        Dim Lb As Label = DirectCast(sender, Label)

    End Sub

    Private Sub cmdOpenLog_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles cmdOpenLog.Click

        Logger.OpenLogFile()

    End Sub

End Class

' ---------------- Ende Datei frmErrorLog.vb  ----------------
' ------------------ Anfang Datei Logger.vb ------------------
Imports System.Text
Imports System.IO

' Durch Verwendung des Interfaces erwirke ich, daß die Intellisense bei Verwendung dieser
' Methoden nur wesentliche Member anbietet

Public Interface ILogger

    Function Add(ByVal ParamArray Segments() As Object) As ILogger

    Sub OpenLogFile()

End Interface

Public Class Logger

    Implements ILogger

    Private _LogFile As String
    Private Shared ReadOnly _Singleton As New Logger
    Private WithEvents _AppDomain As AppDomain

    Private _Writer As StreamWriter

    Private Sub New()

        Dim Segments As String() = { Environment.GetFolderPath( _
            Environment.SpecialFolder.ApplicationData), Application.CompanyName, _
            Application.ProductName, "Errors", "Error.txt"}

        _LogFile = String.Join(Path.DirectorySeparatorChar, Segments)

        Dim sDir As String = Path.GetDirectoryName(_LogFile)

        If Not Directory.Exists(sDir) Then Directory.CreateDirectory(sDir)
        _Writer = New StreamWriter(_LogFile, Append:=False, Encoding:=Encoding.UTF8)
        _AppDomain = AppDomain.CurrentDomain

    End Sub

    Public Shared Function Entry(ByVal ParamArray Segments() As Object) As ILogger

        Return _Singleton.Entry1(Segments)

    End Function

    Public Shared Sub OpenLogFile()

        _Singleton.OpenLogFile1()

    End Sub

    Private Function Entry1(ByVal ParamArray Segments() As Object) As ILogger

        ' Die Einträge können auch wesentlich aufwändiger formatiert werden (z.B. Xml generieren).
        ' z.B. könnte hier auch ein Timestamp generiert werden.
        _Writer.WriteLine()
        Add(Segments)
        Return Me

    End Function

    Private Function Add(ByVal ParamArray Segments() As Object) As ILogger _
                Implements ILogger.Add

        For Each Obj As Object In Segments

            If Obj Is Nothing Then
                _Writer.Write("#Null#")

            Else

                _Writer.Write(Obj.ToString)
            End If

        Next

        _Writer.WriteLine()

        ' Da Add() den Singleton selbst zurückgibt, kann man mehrere Aufrufe aneinanderketten.
        ' Das schreibt sich einfacher als ein With-Block und ist z.T. sogar besser lesbar.
        Return Me

    End Function

    Private Sub OpenLogFile1() Implements ILogger.OpenLogFile

        _Writer.Flush() ' akt. Puffer wegschreiben

        ' LogFile mit Extension-spezifischer Anwendung öffnen
        System.Diagnostics.Process.Start(_LogFile)

    End Sub

    Private Sub AppDomain_ProcessExit(ByVal sender As Object, ByVal e As System.EventArgs) _
                Handles _AppDomain.ProcessExit

        _Writer.Dispose()

    End Sub

    Private Sub AppDomain_UnhandledException( _
                ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs) _
                Handles _AppDomain.UnhandledException

        If e.IsTerminating Then _Writer.Dispose()

    End Sub

End Class

' ------------------- Ende Datei Logger.vb -------------------
' ------------ Ende Projektdatei ErrorLog.vbproj  ------------
' ------------- Ende Projektgruppe ErrorLog.sln  -------------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.