Event Logging


The system administrator uses the Event Viewer to get critical and warning information about the system and applications. You should write error messages from your application to the event log, so the information can be read with the Event Viewer.

Trace messages can be written to the event log if you configure the EventLogTraceListener class. The EventLogTraceListener has an EventLog object associated with it to write the event log entry. You can also use the EventLog class directly to write and read event logs.

In this section, you explore the following:

  • Event-logging architecture

  • Classes for event logging from the System.Diagnostics namespace

  • Adding event logging to services and to other application types

  • Creating an event log listener with the EnableRaisingEvents property of the EventLog class

Figure 17-3 shows an example of a log entry from a service from SQL Server.

image from book
Figure 17-3

For custom event logging, you can use classes from the System.Diagnostics namespace.

Event Logging Architecture

The event log information is stored in several log files. The most important ones are application, security, and system. Looking at the registry configuration of the event log service, you’ll notice several entries under HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog with configurations pointing to the specific files. The system log file is used from the system and device drivers. Applications and services write to the application log. The security log is a read-only log for applications. The auditing feature of the operating system uses the security log. Every application can also create a custom category and log file to write event log entries there. For example, this is done by Windows OneCare and Media Center.

You can read these events by using the administrative tool Event Viewer. The Event Viewer can be started directly from the Server Explorer of Visual Studio by right-clicking on the Event Logs item and selecting the Launch Event Viewer entry from the context menu. The Event Viewer is shown in Figure 17-4.

image from book
Figure 17-4

In the event log, you can see this information:

  • Type - The type can be Information, Warning, or Error. Information is an infrequent successful operation, Warning a problem that’s not immediately significant, and Error a major problem. Additional types are FailureAudit and SuccessAudit, but these types are used only for the security log.

  • Date - Date and Time show the time when the event occurred.

  • Source - The Source is the name of the software that logs the event. The source for the application log is configured in:

     HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog \Application\[ApplicationName]

    Below this key, the value EventMessageFile is configured to point to a resource DLL that holds error messages.

  • Category - A Category can be defined so that event logs can be filtered when using the Event Viewer. Categories can be defined by an event source.

  • Event identifier - The Event identifier specifies a particular event message.

Event Logging Classes

The System.Diagnostics namespace has some classes for event logging, which are shown in the following table.

Open table as spreadsheet

Class

Description

EventLog

With the EventLog class you can read and write entries in the event log, and establish applications as event sources.

EventLogEntry

The EventLogEntry class represents a single entry in the event log. With the EventLogEntryCollection, you can iterate through EventLogEntry items.

EventLogInstaller

The EventLogInstaller class is the installer for an EventLog component. EventLogInstaller calls EventLog.CreateEventSource() to create an event source.

EventLogTraceListener

With the help of the EventLogTraceListener, traces can be written to the event log. This class implements the abstract class TraceListener.

The heart of event logging is in the EventLog class. The members of this class are explained in the following table.

Open table as spreadsheet

EventLog Members

Description

Entries

With the Entries property, you can read event logs. Entries returns a EventLogEntryCollection that contains EventLogEntry objects holding information about the events. There’s no need to invoke a Read() method. The collection is filled as soon as you access this property.

Log

Specify the log for reading or writing event logs with the Log property.

LogDisplayName

LogDisplayName is a read-only property that returns the display name of the log.

MachineName

With the MachineName, you can specify the system on which to read or write log entries.

Source

The Source property specifies the source of the event entries to write.

CreateEventSource()

The CreateEventSource() creates a new event source and a new log file, if a new log file is specified with this method.

DeleteEventSource()

To get rid of an event source, you can invoke DeleteEventSource().

SourceExists()

Before creating an event source, you can verify if the source already exists by using this element.

WriteEntry() WriteEvent()

Write event log entries with either the WriteEntry() or WriteEvent() method. WriteEntry() is simpler, as you just have to pass a string. WriteEvent() is more flexible. Here, you can use message files that are independent of the application and also support localization.

Clear()

The Clear() method removes all entries from an event log.

Delete()

The Delete() method deletes a complete event log.

Creating an Event Source

Before writing events, you must create an event source. You can either use the CreateEventSource() method of the EventLog class or the class EventLogInstaller. Because you need administrative privileges when creating an event source, an installation program would be best for defining the new source.

Tip 

Chapter 15, “Deployment,” explains how to create installation programs.

The following sample verifies that an event log source named EventLogDemoApp already exists. If it doesn’t exist, an object of type EventSourceCreationData is instantiated that defines the source name EventLogDemoApp and the log name ProCSharpLog. Here, all events of this source are written to the ProCSharpLog event log. The default is the application log.

  if (!EventLog.SourceExists("EventLogDemoApp")) {    EventSourceCreationData eventSourceData =          new EventSourceCreationData("EventlogDemoApp", "ProCSharpLog");    EventLog.CreateEventSource(eventSourceData); } 

The name of the event source is an identifier of the application that writes the events. For the system administrator reading the log, the information helps in identifying the event log entries to map them to application categories. Examples of names for event log sources are LoadPerf for the performance monitor, MSSQLSERVER for Microsoft SQL Server, MsiInstaller for the Windows Installer, Winlogon, Tcpip, Time-Service, and so on.

Setting the name Application for the event log writes event log entries to the application log. You can also create your own log by specifying a different application log name. Log files are located in the directory <windows>\System32\WinEvt\Logs.

With the EventSourceCreationData, you can also specify several more characteristics for the event log, as shown in the following table.

Open table as spreadsheet

EventSourceCreationData

Description

Source

The property Source gets or sets the name of the event source.

LogName

LogName defines the log where event log entries are written. The default is the application log.

MachineName

With MachineName you can define the system to read or write log entries.

CategoryResourceFile

With the CategoryResourceFile property you can define a resource file for categories. Categories can be used for an easier filtering of event log entries within a single source.

CategoryCount

The CategoryCount property defines the number of categories in the category resource file.

MessageResourceFile

Instead of specifying that the message should be written to the event log in the program that writes the events, messages can be defined in a resource file that is assigned to the MessageResourceFile property. Messages from the resource file are localizable.

ParameterResourceFile

Messages in a resource file can have parameters. The parameters can be replaced by strings defined in a resource file that is assigned to the ParameterResourceFile property.

Writing Event Logs

For writing event log entries, you can use the WriteEntry() or WriteEvent() methods of the EventLog class.

The EventLog class has both a static and an instance method WriteEntry(). The static method WriteEntry() requires a parameter of the source. The source can also be set with the constructor of the EventLog class. Here in the constructor the log name, the local machine and the event source name are defined. Next three event log entries are written with the message as the first parameter of the WriteEntry() method. WriteEntry() is overloaded. The second parameter you can assign is an enumeration of type EventLogEntryType. With EventLogEntryType, you can define the severity of the event log entry. Possible values are Information, Warning, and Error, and for auditing SuccessAudit and FailureAudit. Depending on the type, different icons are shown in the Event Viewer. With the third parameter you can specify an application-specific event ID that can be used by the application itself. In addition to that, you can also pass application-specific binary data and a category.

  EventLog log = new EventLog("ProCSharpLog", ".", "EventLogDemoApp"); log.WriteEntry("Message 1"); log.WriteEntry("Message 2", EventLogEntryType.Warning); log.WriteEntry("Message 3", EventLogEntryType.Information, 33); log.Dispose(); 

Resource Files

Instead of defining the messages for the event log in the C# code and passing it to the WriteEntry() method, you can create a message resource file, define messages in the resource file, and pass message identifiers to the WriteEvent() method. Resource files also support localization.

Tip 

Message resource files are native resource files that have nothing in common with .NET resource files. .NET resource files are covered in Chapter 20, “Localization.”

A message file is a text file with the mc file extension. The syntax that this file uses to define messages is very strict. The sample file EventLogMessages.mc contains four categories followed by event messages. Every message has an ID that can be used by the application writing event entries. Parameters that can be passed from the application are defined with % syntax in the message text.

Tip 

For the exact syntax of message files, check the MSDN documentation for Message Text Files.

  ; // EventLogDemoMessages.mc ; // ******************************************************** ; // - Event categories - ; // Categories must be numbered consecutively starting at 1. ; // ******************************************************** MessageId=0x1 Severity=Success SymbolicName=INSTALL_CATEGORY Language=English Installation . MessageId=0x2 Severity=Success SymbolicName=DATA_CATEGORY Language=English Database Query . MessageId=0x3 Severity=Success SymbolicName=UPDATE_CATEGORY Language=English Data Update . MessageId=0x4 Severity=Success SymbolicName=NETWORK_CATEGORY Language=English Network Communication . ; // - Event messages - ; // ********************************* MessageId = 1000 Severity = Success Facility = Application SymbolicName = MSG_CONNECT_1000 Language=English Connection successful. . MessageId = 1001 Severity = Error Facility = Application SymbolicName = MSG_CONNECT_FAILED_1001 Language=English Could not connect to server %1. . MessageId = 1002 Severity = Error Facility = Application SymbolicName = MSG_DB_UPDATE_1002 Language=English Database update failed. . MessageId = 1003 Severity = Success Facility = Application SymbolicName = APP_UPDATE Language=English Application %%5002 updated. . ; // - Event log display name - ; // ******************************************************** MessageId = 5001 Severity = Success Facility = Application SymbolicName = EVENT_LOG_DISPLAY_NAME_MSGID Language=English Professional C# Sample Event Log . ; // - Event message parameters - ; //   Language independent insertion strings ; // ******************************************************** MessageId = 5002 Severity = Success Facility = Application SymbolicName = EVENT_LOG_SERVICE_NAME_MSGID Language=English EventLogDemo.EXE . 

Use the Messages Compiler, mc.exe, to create a binary message file. mc –s EventLogDemoMessages.mc compiles the source file containing the messages to a messages file with the .bin extension and the file Messages.rc, which contains a reference to the binary message file.

 mc -s EventLogDemoMessages.mc 

Next, you must use the Resource Compiler, rc.exe. rc EventLogDemoMessages.rc creates the resource file Messages.res.

 rc EventLogDemoMessages.rc 

With the linker, you can bind the binary message file EventLogDemoMessages.Res to a native DLL.

 link /DLL /SUBSYSTEM:WINDOWS /NOENTRY /MACHINE:x86 EventLogDemoMessages.Res 

Now, you can register an event source that defines the resource files as shown in the following code. First a check is done if the event source named EventLogDemoApp exists. If the event log must be created because it does not exist, the next check verifies if the resource file is available. Some samples in the MSDN documentation demonstrate writing the message file to the <windows>\system32 directory, but you shouldn’t do that. Copy the message DLL to a program-specific directory that you can get with the SpecialFolder enumeration value ProgramFiles. If you need to share the messages file among multiple applications, you can put it into Environment.SpecialFolder.CommonProgramFiles. If the file exists, a new object of type EventSourceCreationData is instantiated. In the constructor, the name of the source and the name of the log are defined. You use the properties CategoryResourceFile, MessageResourceFile, and ParameterResourceFile to define a reference to the resource file. After the event source is created, you can find the information on the resource files in the registry with the event source. The method CreateEventSource registers the new event source and log file. Finally, the method RegisterDisplayName() from the EventLog class specifies the name of the log as it is displayed in Event Viewer. The ID 5001 is taken from the message file.

Tip 

If you want to delete a previously created event source, you can do so with EventLog.DeleteEventSource(sourceName);. To delete a log you can invoke EventLog.Delete(logName);.

  string logName = "ProCSharpLog"; string sourceName = "EventLogDemoApp"; string resourceFile = Environment.GetFolderPath(       Environment.SpecialFolder.ProgramFiles) +       @"\procsharp\EventLogDemoMessages.dll"; if (!EventLog.SourceExists(sourceName)) {    if (!File.Exists(resourceFile))    {       Console.WriteLine("Message resource file does not exist");       return;    }    EventSourceCreationData eventSource =          new EventSourceCreationData(sourceName, logName);    eventSource.CategoryResourceFile = resourceFile;    eventSource.CategoryCount = 4;    eventSource.MessageResourceFile = resourceFile;    eventSource.ParameterResourceFile = resourceFile;    EventLog.CreateEventSource(eventSource); } else {    logName = EventLog.LogNameFromSourceName(sourceName, "."); } EventLog evLog = new EventLog(logName, ".", sourceName); evLog.RegisterDisplayName(resourceFile, 5001); 

Now, you can use the WriteEvent() method instead of WriteEntry() to write the event log entry. WriteEvent() requires an object of type EventInstance as parameter. With the EventInstance, you can assign the message ID, the category, and the severity of type EventLogEntryType. WriteEvent() accepts besides the EventInstance parameters for messages with parameters and binary data as byte array.

  EventLog log = new EventLog(logName, ".", sourceName); EventInstance info1 = new EventInstance(1000, 4,       EventLogEntryType.Information); log.WriteEvent(info1); EventInstance info2 = new EventInstance(1001, 4, EventLogEntryType.Error); log.WriteEvent(info2, "avalon"); EventInstance info3 = new EventInstance(1002, 3, EventLogEntryType.Error); byte[] addionalInfo = { 1, 2, 3 }; log.WriteEvent(info3, addionalInfo); log.Dispose(); 

Tip 

For the message identifiers, it is useful to define a class with const values that provide a more meaningful name for the identifiers in the application.

You can read the event log entries with the Event Viewer.

Event Log Listener

Instead of using the Event Viewer to read event log entries, you can also create a custom event log reader that listens for events of specified types as needed. You can create a reader where important messages pop up to the screen, or send SMS to a system administrator.

Next, you write an application that receives an event when a service encounters a problem. Create a simple Windows application that monitors the events of your Quote service. This Windows application consists of a list box and an Exit button only, as shown in Figure 17-5.

image from book
Figure 17-5

Add an EventLog component to the design view by dragging and dropping it from the toolbox. Set the Log property to Application. You can set the Source property to a specific source to only receive event log entries from this source, for example the source EventLogDemoApp for receiving the event logs from the application created previously. If you leave the Source property empty, you will get events from every source. You also need to change the property EnableRaisingEvents. The default value is false; setting it to true means that an event is generated each time this event occurs, and you can add an event handler for the EntryWritten event of the EventLog class. Add a handler with the name OnEntryWritten() to this event.

The OnEntryWritten() handler receives an EntryWrittenEventArgs object as argument, from which you can get the complete information about an event. With the Entry property, an EventLogEntry object with information about the time, event source, type, category, and so on is returned:

  protected void OnEntryWritten (object sender,    System.Diagnostics.EntryWrittenEventArgs e) {    StringBuilder sb = new StringBuilder();    sb.AppendFormat("{0} {1} {2}",          e.Entry.TimeGenerated.ToShortTimeString(),          e.Entry.Source,          e.Entry.Message);    listBoxEvents.Items.Add(sb.ToString()); } 

The running application displays event log information, as shown in Figure 17-6.

image from book
Figure 17-6




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net