| [ Team LiB ] |
|
20.2 Programming the Event Log ServiceThe .NET Framework exposes ELS functionality through the System.Diagnotics.EventLog class; Table 20-3 summarizes the public members of the EventLog class.
In the following sections, we demonstrate how to use the EventLog class to program the ELS. The EventLog class does not expose all of the ELS functionality, and some advanced features are not available. You must use the unmanaged Windows API to gain access to the complete ELS feature set; see the Windows API documentation for details.
Many of the examples that follow demonstrate how to program the ELS of a remote computer. This functionality requires that a trust relationship is established; consult the Windows documentation for details of how to perform this task. 20.2.1 Querying the Event Log SystemThe EventLog class defines members that query the ELS for information about event logs. The static GetEventLogs method returns all of the event logs on a specified computer, represented as an array of EventLog instances. The following statements demonstrate how to use this method to obtain a list of event log names on the local computer: # C#
// get the event logs installed on the local machine
EventLog[] x_logs = EventLog.GetEventLogs( );
// run through the array of event logs and print out the names
foreach (EventLog x_log in x_logs) {
Console.WriteLine("Log Name: {0}", x_log.Log);
}
# Visual Basic .NET
' get the event logs installed on the local machine
Dim x_logs( ) As EventLog = EventLog.GetEventLogs( )
' run through the array of event logs and print out the names
Dim x_log As EventLog
For Each x_log In x_logs
Console.WriteLine("Log Name: {0}", x_log.Log)
Next
The output these statements produce depends on the configuration of your computer; our results are below, showing that our computer has only the three default logs: Log Name: Application Log Name: Security Log Name: System We can enumerate the event logs on another computer by using the overloaded version of the GetEventLog method, which accepts the computer name as an argument, as shown below for the computer called FILESERVER: # C#
// get the event logs installed on another computer
EventLog[] x_logs = EventLog.GetEventLogs("FILESERVER");
# Visual Basic .NET
' get the event logs installed on another computer
Dim x_logs( ) As EventLog = EventLog.GetEventLogs("FILESERVER")
We can determine if a specific log exists by using the static Exists method; the following statements demonstrate how to test for the existence of a log called MyEventLog—see the Section 20.2.5 for details of how to create and delete event logs: # C#
bool x_log_exists = EventLog.Exists("MyEventLog");
Console.WriteLine("Log Exists: {0}", x_log_exists);
# Visual Basic .NET
Dim x_log_exists As Boolean = EventLog.Exists("MyEventLog")
Console.WriteLine("Log Exists: {0}", x_log_exists)
The following statements determine the existence of MyEventLog on the computer called FILESERVER, using the overloaded form of the Exists method: # C#
bool x_log_exists = EventLog.Exists("MyEventLog", "FILESERVER");
Console.WriteLine("Log Exists: {0}", x_log_exists);
# Visual Basic .NET
Dim x_log_exists As Boolean = EventLog.Exists("MyEventLog", "FILESERVER")
Console.WriteLine("Log Exists: {0}", x_log_exists)
20.2.2 Using Event SourcesWe register an event source with the static CreateEventSource method; this is an overloaded method with forms that register an event source locally or on another computer. The following statements demonstrate how to register an event source named MyEventSource, associated with the Application event log on the local computer and a second event source named MyOtherEventSource associated with the System event log on the FILESERVER computer: # C#
// create "MyEventSource" on the local computer
EventLog.CreateEventSource("MyEventSource", "Application");
// create "MyOtherEventSource" on the FILESERVER computer
EventLog.CreateEventSource("MyOtherEventSource", "System", " FILESERVER ");
# Visual Basic .NET
' create "MyEventSource" on the local computer
EventLog.CreateEventSource("MyEventSource", "Application")
' create "MyOtherEventSource" on the FILESERVER computer
EventLog.CreateEventSource("MyOtherEventSource", "System", "FILESERVER")
If you do not specify an event log name as an argument to the CreateEventSource method (by using the empty string ""), the event source will be associated with the Application log. Event sources are persistent, as we explained in Section 20.1.2 of this chapter; attempting to register an event source that already exists throws an instance of the System.ArgumentException exception class. We can check to see if an event source has been registered using the static SourceExists method; the following statements demonstrate how to use this method to ensure that our two example event sources are registered and will create them if they are not: # C#
// check to see if we need to create the local event source
if (!EventLog.SourceExists("MyEventSource")) {
// create "MyEventSource" on the local computer
EventLog.CreateEventSource("MyEventSource", "Application");
}
// check to see if we need to create the remote event source
if (!EventLog.SourceExists("MyOtherEventSource", "FILESERVER")) {
// create "MyOtherEventSource" on the FILESERVER computer
EventLog.CreateEventSource("MyOtherEventSource", "System", "FILESERVER");
}
# Visual Basic .NET
' check to see if we need to create the local event source
If Not EventLog.SourceExists("MyEventSource") Then
' create "MyEventSource" on the local computer
EventLog.CreateEventSource("MyEventSource", "Application")
End If
' check to see if we need to create the remote event source
If Not EventLog.SourceExists("MyOtherEventSource", "FILESERVER") Then
' create "MyOtherEventSource" on the FILESERVER computer
EventLog.CreateEventSource("MyOtherEventSource", "System", "FILESERVER")
End If
The static LogNameFromSourceName method determines the log with which an event source is associated, as shown by the following statements: # C#
// obtain the name of the log associated with the local event source
string x_log_name = EventLog.LogNameFromSourceName("MyEventSource", ".");
// write out the log name
Console.WriteLine(x_log_name);
// obtain the name of the log associated with the remote event source
x_log_name = EventLog.LogNameFromSourceName("MyOtherEventSource", "FILESERVER");
// write out the log name
Console.WriteLine(x_log_name);
# Visual Basic .NET
' obtain the name of the log associated with the local event source
Dim x_log_name As String = EventLog.LogNameFromSourceName("MyEventSource", ".")
' write out the log name
Console.WriteLine(x_log_name)
' obtain the name of the log associated with the remote event source
x_log_name = EventLog.LogNameFromSourceName("MyOtherEventSource", "FILESERVER")
' write out the log name
Console.WriteLine(x_log_name)
Notice that unlike the other methods covered in this section, the LogNameFromSourceName method does not have separate overridden forms for dealing with local and remote computers; the local machine is specified by a period. We can remove an event source registration by using the overloaded DeleteEventSource method. The following statements demonstrate how to remove the event sources we created earlier: # C#
// delete the local event source
EventLog.DeleteEventSource("MyEventSource");
// delete the remote event source
EventLog.DeleteEventSource("MyOtherEventSource", "FILESERVER");
# Visual Basic .NET
' delete the local event source
EventLog.DeleteEventSource("MyEventSource")
' delete the remote event source
EventLog.DeleteEventSource("MyOtherEventSource", "FILESERVER")
Attempting to delete an event source that is not registered (or whose registration has already been removed) will throw an instance of System.ArgumentException. 20.2.3 Reading Event LogsThe first step towards reading the contents of an event log is to create a new instance of the EventLog class, specifying the name of the log we want to read from as a constructor argument. The following statements demonstrate how to create new instances of the EventLog that refer to the local Application log and the System log on the FILESERVER computer: # C#
// create a new instance that refers to the local Application log
EventLog x_local_log = new EventLog("Application");
// create a new instance which refers to the System log on FILESERVER
EventLog x_remote_log = new EventLog("System", "FILESERVER");
# Visual Basic .NET
' create a new instance that refers to the local Application log
Dim x_local_log As EventLog = New EventLog("Application")
' create a new instance which refers to the System log on FILESERVER
Dim x_remote_log As EventLog = New EventLog("System", "FILESERVER")
Once we have created an instance of the EventLog class, we can call the Entries property, which returns an instance of the EventLogEntryCollection class, containing the events in the log. Table 20-4 summarizes the public methods of the EventLogEntryCollection class, which implements the System.Collections.ICollection and System.Collections.IEnumerable interfaces.
The EventLogEntryCollection class represents the collection of events stored in a log, each of which is represented by an instance of the EventLogEntry class. Table 20-5 summarizes the public members of the EventLogEntry class; not all of the properties relate to ELS functionality supported by the .NET EventLog class. Consult the Windows API documentation for details of advanced ELS functionality.
The following statements demonstrate how to use the EventLog.Entries property to obtain an EventLogEntryCollection for the Application log and print out details of the events using the EventLogEntry class: # C#
// create a new instance that refers to the local Application log
EventLog x_local_log = new EventLog("Application");
// obtain a collection of the events through the Entries property
EventLogEntryCollection x_collection = x_local_log.Entries;
// write out the number of events in the log
Console.WriteLine("There are {0} entries in the event log", x_collection.Count);
// iterate through the entry collection and write out information
// about each event in turn
foreach (EventLogEntry x_entry in x_collection) {
Console.WriteLine("Event Source: {0}, Event ID {1}, Event Message {2}",
x_entry.Source, x_entry.EventID, x_entry.Message);
}
# Visual Basic .NET
' create a new instance that refers to the local Application log
Dim x_local_log As EventLog = New EventLog("Application")
' obtain a collection of the events through the Entries property
Dim x_collection As EventLogEntryCollection = x_local_log.Entries
' write out the number of events in the log
Console.WriteLine("There are {0} entries in the event log", x_collection.Count)
' iterate through the entry collection and write out information
' about each event in turn
Dim x_entry As EventLogEntry
For Each x_entry In x_collection
Console.WriteLine("Event Source: {0}, Event ID {1}, Event Message {2}", _
x_entry.Source, x_entry.EventID, x_entry.Message)
Next
20.2.4 Writing EventsThe first step towards writing events is to create an instance of the EventLog class configured for the log and the computer that you wish to receive your event data; the following statements demonstrate how to use the overloaded EventLog constructor to create instances that refer to the Application log on the local and FILESERVER computers: # C#
// create a new instance that refers to the local Application log
EventLog x_local_log = new EventLog("Application");
// create a new instance that refers to the remote Application Log
EventLog x_remote_log = new EventLog("Application", "FILESEVER");
# Visual Basic .NET
' create a new instance that refers to the local Application log
Dim x_local_log As EventLog = New EventLog("Application")
' create a new instance that refers to the remote Application Log
Dim x_remote_log As EventLog = New EventLog("Application", "FILESEVER")
We can achieve the same affect by using the default EventLog constructor in conjunction with the MachineName and Log properties, as illustrated by the following statements (had we wanted to refer to the local machine we would have set the MachineName property to be a period): # C# // create a new instance that refers to the local Application log EventLog x_local_log = new EventLog( ); x_local_log.MachineName = "FILESERVER"; x_local_log.Log = "Application"; # Visual Basic .NET ' create a new instance that refers to the local Application log Dim x_local_log As EventLog = New EventLog( ) x_local_log.MachineName = "FILESERVER" x_local_log.Log = "Application" Having created the EventLog instance, we must specify the event source that we want to use when writing an event; we do this with the Source property, as the following statements show: # C#
// create a new instance that refers to the local Application log
EventLog x_local_log = new EventLog("Application");
// specify the event source that we'll use to record events
x_local_log.Source = "MyEventSource";
# Visual Basic .NET
' create a new instance that refers to the local Application log
Dim x_local_log As EventLog = New EventLog("Application")
' specify the event source that we'll use to record events
x_local_log.Source = "MyEventSource"
Once we have specified the computer, the event log, and the event source to use, we can use the WriteEntry method to write an event to the log; this method is overloaded with 10 different versions, which allows you to log an event with increasing levels of detail. The simplest version of the WriteEntry method accepts only the human-readable message element, whereas the most complex version accepts values for all of the event structure elements we described in Section 20.1.3. In the following statements, we write an error message to log an unexpected process-termination event to the Application log on the local computer: # C#
// create a new instance that refers to the local Application log
EventLog x_local_log = new EventLog( );
x_local_log.MachineName = ".";
x_local_log.Log = "Application";
// specify the event source that we'll use to record events
x_local_log.Source = "MyEventSource";
// define the binary data that will assist in debugging the problem
byte[] x_debugging_data = new byte[] {0xCA, 0xFE};
// write the event
x_local_log.WriteEntry(
"MyApplication exited unexpectedly", // this is the event message
EventLogEntryType.Error, // specify an error message
100, // this is the application-specific ID
200, // this is the application-specific category
x_debugging_data // this is the binary data
);
# Visual Basic .NET
' create a new instance that refers to the local Application log
Dim x_local_log As EventLog = New EventLog( )
x_local_log.MachineName = "."
x_local_log.Log = "Application"
' specify the event source that we'll use to record events
x_local_log.Source = "MyEventSource"
' define the binary data that will assist in debugging the problem
Dim x_debugging_data( ) As Byte = New Byte( ) {&HCA, &HFE}
' write the event
x_local_log.WriteEntry( _
"MyApplication exited unexpectedly", _
EventLogEntryType.Error, _
100, _
200, _
x_debugging_data _
)
We specify the type of event we want to write by using a value from the System.Diagnostics.EventLogEntryType enumeration; Table 20-6 lists the defined values, which correspond to the event types detailed in Table 20-2.
20.2.5 Using Custom Event LogsYou can create custom event logs by specifying the name you wish to use with the Log property of the EventLog class. When you write the first event to the log with the WriteEntry method, the ELS will create the custom log automatically. The event source specified by the Source property will be registered and associated with the new custom log. The following statements demonstrate how to create the custom log MyCustomEventLog; ELS does not create the custom log until the WriteEntry statement is executed: # C#
// create a new instance that refers to the custom log
EventLog x_local_log = new EventLog( );
x_local_log.MachineName = ".";
x_local_log.Log = "MyCustomEventLog";
// specify the event source that we'll use to record events
x_local_log.Source = "MyCustomEventSource";
// write a log entry - the custom log will not be created until this point
x_local_log.WriteEntry("MyApplication exited unexpectedly");
# Visual Basic .NET
' create a new instance that refers to the custom log
Dim x_local_log As EventLog = New EventLog( )
x_local_log.MachineName = "."
x_local_log.Log = "MyCustomEventLog"
' specify the event source that we'll use to record events
x_local_log.Source = "MyCustomEventSource"
' write a log entry - the custom log will not be created until this point
x_local_log.WriteEntry("MyApplication exited unexpectedly")
Custom logs can be deleted with the Delete method defined by the EventLog class, as demonstrated by the following statements: # C#
// delete the custom event log
EventLog.Delete("MyCustomEventLog");
# Visual Basic .NET
' delete the custom event log
EventLog.Delete("MyCustomEventLog")
Use the Delete method with caution; the event log will be removed and all of the entries and event sources will be lost permanently. An instance of the System.InvalidOperationException exception is thrown by the Delete method if you attempt to delete a log that does not exist.
20.2.6 Monitoring Event LogsThe EventLog class provides an event mechanism that allows us to monitor an event log. In this section, we demonstrate how to use this feature, which relies on the .NET event delegate mechanism; consult the .NET documentation if you are unfamiliar with .NET delegates. We can register for event notification by adding an instance of the EntryWrittenEventHandler delegate to the EntryWritten event defined by the EventLog class, as demonstrated by the statements below. The delegate method signature defines the EntryWrittenEventArgs class, which makes the event that has been written available as an instance of EventLogEntry accessible through the Entry property: # C#
using System;
using System.Diagnostics;
public class EventLogMonitor {
public static void Main( ) {
// create a new instance of the EventLog class
EventLog x_local_log = new EventLog("MyCustomEventLog");
// create a delegate to process events from the ELS
EntryWrittenEventHandler x_handler
= new EntryWrittenEventHandler(MyOnEntryWrittenMethod);
// add the delegate to the EventLog event
x_local_log.EntryWritten += x_handler;
// enable event processing
x_local_log.EnableRaisingEvents = true;
// wait to read a lone from the console - just to stop
// the application from exiting
Console.ReadLine( );
}
public static void MyOnEntryWrittenMethod(object p_source,
EntryWrittenEventArgs p_args) {
// extract the event object from the event arguments
EventLogEntry x_entry = p_args.Entry;
// write out the event details
Console.WriteLine("Event Source: {0}, Event ID {1}, Event Message {2}",
x_entry.Source, x_entry.EventID, x_entry.Message);
}
}
# Visual Basic .NET
Imports System.Diagnostics
Class EventLogMonitor
Shared Sub Main( )
' create a new instance of the EventLog class
Dim x_local_log As EventLog = New EventLog("MyCustomEventLog")
' create a delegate to process events from the ELS
AddHandler x_local_log.EntryWritten, AddressOf MyOnEntryWrittenMethod
' enable event processing
x_local_log.EnableRaisingEvents = True
' wait to read a lone from the console - just to stop
' the application from exiting
Console.ReadLine( )
End Sub
Public Shared Sub MyOnEntryWrittenMethod(ByVal p_source As Object, _
ByVal p_args As EntryWrittenEventArgs)
' extract the event object from the event arguments
Dim x_entry As EventLogEntry = p_args.Entry
' write out the event details
Console.WriteLine("Event Source: {0}, Event ID {1}, Event Message {2}", _
x_entry.Source, x_entry.EventID, x_entry.Message)
End Sub
End Class
Events will not be raised until the value of the EnableRaisingEvents property is set to true (C#) or True (Visual Basic .NET). The EventWritten event is raised five seconds after an entry has been added to the monitored event log; if several events have been written during the five-second period, only the last event will be signaled via the delegate.
|
| [ Team LiB ] |
|