Using the EventLog Class in VB.NET

Information is the cornerstone of our economy. Information is also key to software development. It is helpful to know what your application is doing as you are assembling core components, during testing, and after the application is shipped.

This information can be available to you at a modest cost without implementing new tools. VB.NET defines the EventLog class in the System.Diagnostics namespace. Using the EventLog class you can gather significant application information about your deployed application, and you can create a new log, logging anything and everything you need while you are building and testing.

A user may not be able to readily reproduce or describe what went wrong while using your application, but if you have logged critical information in your deployed application, the user can export and mail you a copy of the event log. If the testers where you work are performing whitebox testing then they can mail you a copy of the custom log, enabling you to scrutinize the behavior of your code in a testing environment.

The Application log does not have an infinite amount of space, suggesting you only log significant details. However, during development and testing you can define a custom log and log as much or as little details as you need. (One additional consideration is that logging information takes time; you may not want to be writing to the event log a lot in a production application as this may make your program sluggish.)

This article demonstrates how to create a custom log, define a log source, manage logs, and respond to log events. Combine deployment logging behavior with testing logging behavior as you are building your classes, and you will have information that may help you resolve problems more quickly.

Creating an Event Source

Your application must be registered as an event source before you can write information to the event log. You can register your application as an event source by calling the shared method EventLog.CreateEventSource. Calling this method adds a registry entry to HKEY_LOCAL_MACHINE\SYSTEM\Services\EventLog, allowing the EventLog service to log information to the log file and display the log in the EventViewer.

If you create the event source in an existing log file then the information is written to the existing .evt file and can be viewed in the EventViewer. For example, if you create an event source in the Application log then when you write information to the log that information will be accessible in Application log section of the Event Viewer (see figure 1). If you define a new log then the Event Viewer will display the new log group and create a new .evt file to store the physical log information. (By default the event files are stored in c:\winnt\system32\config directory.

Figure 1: The Event Viewer displaying event log information.

(The example code for this article was defined in a class, MyEventLog, for convenience.) The listing that follows combines the shared method SourceExists with the CreateEventSource to create a new event log and register an event source.

Public Shared ReadOnly Property Name() As String
  Get
    Return "EventLogDemo"
  End Get
End Property

Public Shared Sub CreateEventSource()
  If (EventLog.SourceExists(Name)) Then Exit Sub
  EventLog.CreateEventSource(Name, Name)
End Sub

The sample code uses a query method, a property, to return a name used for the log and source. Name will be used as the name of the event log and the event source. After the shared method EventLog.CreateEventSource is called the Event Viewer will list the new log source as shown in figure 2.

Figure 2: The Event Viewer has been updated to show the new log, EventLogDemo, after the call to EventLog.CreateEventSource.

Logging an Event

All you need to do to write an entry to the event log is call WriteEntry (see figure 3), passing the source name and the message to the shared EventLog.WriteEntry method. The code in the next listing illustrates how the event entry shown in figure 3 was created.

Figure 3: Shows an entry written to the event log.

Private Shared Function Formatted(ByVal Message _
                                  As String) As String
  Return String.Format("{0}: {1}", Now, Message)
End Function

Public Shared Sub WriteEntry(ByVal Message As String)
  EventLog.WriteEntry(Name, Formatted(Message))
End Sub

Literally, all you need is the line of code EventLog.WriteEntry to create the event log entry. Calling MyEventLog.WriteEntry(www.codeguru.com) where MyEventLog is the name of the class containing the shared methods shown will create the entry shown in figure 3. The Name argument comes from the shared read only property introduced earlier. (As mentioned the code listings were taken from a class that demonstrates several of the capabilities of the EventLog.) There are five overloaded WriteEntry methods, including one form that allows you to select an enumeration that indicates an icon that will be drawn in the log entry.

If you call WriteEntry without creating an event source then the source named in WriteEntry will be created in the Application log by default. Source names are unique across all logs; you may not create an event source with the same name in more than one log.

Finding a Log, Given the Source Name

If you have the name of an event source then you can programmatically determine the log file name that contains that source. Call the shared method EventLog.LogNameFromSourceName, passing the source name and the machine name to search all logs. For example,

EventLog.LogNameFromSourceName("EventLogDemo", ".")

Demonstrates how to retrieve the name of the log containing the “EventLogDemo” source on the current machine. The argument “.” is the remote machine argument; “.” represents the current machine.

Handling Log Events

When you want feedback indicating when entries are written to the event log, you will need to create an instance of the EventLog class and associate a delegate to the EntryWritten event. The listing that follows demonstrates an event handler, how to create an instance of the EventLog class, and associate a delegate with the EntryWritten event.

Public Shared Sub OnEntryWritten(ByVal sender As System.Object, _
  ByVal e As EntryWrittenEventArgs)

  Console.WriteLine(e.Entry)

End Sub

Public Shared Sub HandleEvent()
  Dim Log As New EventLog()
  Try
    AddHandler Log.EntryWritten, AddressOf MyEventLog.OnEntryWritten
    Log.WriteEntry(Name, "This is a test!")
  Finally
    Log.Close()
  End Try
End Sub

OnEntryWritten shows the signature of an event handler for the EventLog.EntryWritten event. The EntryWritten event handler is a sub routine that takes an Object and a System.Diagnostics.EntryWrittenEventArgs argument. The event handler demonstrated writes the Entry text to the Console using the WriteLine method. The HandleEvent method creates an instance of the EventLog class, and associates a delegate—represented by AddressOf MyEventLog.OnEntryWritten, where MyEventLog is the name of the class containing the code shown in the listingwith the EntryWritten event. Log.WriteEntry writes some text to the event log, and the finally block closes the log.

We need to review a couple of points here. The EventLog class is in the System.Diagnostics namespace; thus the code assumes we have an imports statement or we can substitute the fully qualified path on the line creating the Log object. Secondly, if it is not apparent, MyEventLog is the name of the class containing the two methods in (and in all of) the example code. Name is the property method introduced earlier in the article. The code shown assumes that you ran earlier code to register the event source, Name returns the name of source, and if you have not pre-registered the event source then be aware that the source will be created in the Application log. The significant point here is that you need an object and a delegate to be notified when event entries are written to a log.

Deleting an Event Source

Event sources are like unique keys. You may only have one instance of a specifically named source in all instances of logs. If you create an event source in one log and want to use that source in another log then you will need to remove the event source from the original log.

The EventLog class defines the DeleteEventSource shared method that allows you to remove an event source, and the Delete method that allows you to delete a log. Precede the call to DeleteEventSource with a sentinel check to ensure the source exists. If you try to delete an un-registered source then you will receive an ArgumentException. The following three statements demonstrate removing an event source and a log with the same name.

If (Not EventLog.SourceExists("EventLogDemo")) Then Exit Sub
EventLog.DeleteEventSource("EventLogDemo")
EventLog.Delete("EventLogDemo")

All three statements call shared methods. The first statement checks to ensure the source is registered (and assuming the three statements are in a sub routine, exits the sub if the source does not exist.) The second statement deletes the event source, and the third statement deletes the log file.

It is up to you whether you create a new log or use an existing one. And, it is up to you when or if you delete a source and remove a log file. Consider using the Application log for event entries that will be written in a deployed application. Use a new log for entries that are only written when you deploy a Debug build for testing purposes. Finally, use compiler directives to manage code that should be included depending on the settings in the Visual Studio IDE Configuration Manager.

About the Author

Paul Kimmel is a freelance writer for Developer.com and CodeGuru.com. He is the founder of Software Conceptions, Inc, founded in 1990. Paul Kimmel performs contract software development services in North America and can be contacted at pkimmel@softconcepts.com.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read