In a
previous post, I had mentioned that I needed something with a little more ‘
oomph’ than the
‘standard’ Windows® Event Viewer. After giving some thought to what type of application to write, I began to contemplate how I was going to access the EventLogs on various machines. For this task I decided to give the
EventLog Class a shot. The
EventLog Class is found in the
System.Diagnostics namespace. During my
‘exploration’ via creating a basic application, I was pleasantly surprised at how easy and fast I was able to create a basic yet functional
EventLog Viewer.
Using
BDS® 2006 (and yes, I also created a version with
VB.NET using
Visual Studio® 2005 -- I wanted to work with some of the
.NET 2.0 changes to the
EventLog Class -- I’ll post that code later), I created a new Windows Form Application.

For this basic application I placed an
ImageList,
TreeView,
ListView and
RichTextBox (separated by splitters to allow for sizing) onto the form. The
‘basic application’ concept was to display the available Event Logs for a computer in the
TreeView. When an event log is selected within the
TreeView, the ListView displays the selected EventLlog's entries. When and entry is selected in the
ListView, the ‘event’ message is displayed in the
RichTextBox. I had placed some images in the
ImageList to cosmetically spruce things up a bit.


Here is the gist of some simple code: (Minor property adjustments and event assignments are not listed, but should be obvious)
const
//Image constants- the image locations in the ImageList
COMPUTERIMG= 0;
LOGIMG= 2;
ERRORIMG= 3;
WARNINGIMG= 4;
INFOIMG= 5;
AUDITIMG= 6;
type
stringarray= array of string;
// In the TWinForm class of the new form
private
strSelEvtLogName: string;
strSelComputerName: string;
procedure AddComputer(mytreeview: TreeView; computername: string);
procedure AppendLogMessage(myrichtextbox: RichTextBox; logname: string;
computername: string; index: Integer);
procedure DisplayLogEntries(mylistview: ListView; logname: string;
computername: string);
function GetEventLogNames(computername: string):stringarray;
// The class code
procedure TWinForm.DisplayLogEntries(mylistview: ListView; logname,
computername: string);
var
e: EventLog;
entry: EventLogEntry;
listitem: ListViewItem;
oldCursor: System.Windows.Forms.Cursor;
begin
e:= EventLog.Create(logname, computername);
oldCursor:= Cursor;
Cursor:= Cursors.WaitCursor;
mylistview.BeginUpdate;
mylistview.Items.Clear;
for entry in e.Entries do
begin
// Set the image index for the entry type
Case entry.EntryType of
EventLogEntryType.Error: begin // 1
listitem:= mylistview.Items.Add('Error');
listitem.ImageIndex:= ERRORIMG;
end;
EventLogEntryType.FailureAudit: begin // 16
listitem:= mylistview.Items.Add('Failure Audit');
listitem.ImageIndex:= AUDITIMG;
end;
EventLogEntryType.Information: begin // 4
listitem:= mylistview.Items.Add('Information');
listitem.ImageIndex:= INFOIMG;
end;
EventLogEntryType.SuccessAudit: begin // 8
listitem:= mylistview.Items.Add('Success Audit');
listitem.ImageIndex:= AUDITIMG;
end;
EventLogEntryType.Warning: begin // 2
listitem:= mylistview.Items.Add('Warning');
listitem.ImageIndex:= WARNINGIMG;
end;
end;
listitem.SubItems.Add(entry.TimeGenerated.ToLocalTime.ToString);
listitem.SubItems.Add(entry.Source);
listitem.SubItems.Add(entry.Category);
// The EventID property has been deprecated. in 2.0
listitem.SubItems.Add(entry.EventID.ToString);
// Note: The InstanceId property is new in the .NET Framework version 2.0.
//listitem.SubItems.Add(entry.InstanceId);
listitem.SubItems.Add(entry.UserName);
listitem.SubItems.Add(entry.MachineName);
//Remarks: Index is not necessarily zero-based. I love stuff like this
listitem.SubItems.Add(entry.Index.ToString);
end;
mylistview.EndUpdate;
Cursor:= oldCursor;
end;
procedure TWinForm.AddComputer(mytreeview: TreeView; computername: string);
var
strNames: stringarray;
strMy: string;
computernode,lognode: TreeNode;
begin
// Get a list of the event logs for a computer
strNames:= GetEventLogNames(computername);
computerNode:= mytreeview.Nodes.Add(computername);
computerNode.ImageIndex:= COMPUTERIMG;
for strMy in strNames do
begin
logNode:= computerNode.Nodes.Add(strMy);
logNode.ImageIndex:= LOGIMG;
logNode.SelectedImageIndex:= logNode.ImageIndex;
end;
end;
procedure TWinForm.AppendLogMessage(myrichtextbox: RichTextBox; logname,
computername: string; index: Integer);
var
e: EventLog;
entry: EventLogEntry;
begin
e:= EventLog.Create(logname, computername);
entry:= e.Entries.Item[index];
myrichtextbox.AppendText(entry.Message);
end;
function TWinForm.GetEventLogNames(computername: string):stringarray;
var
c: Integer;
eventlogs: array of EventLog;
e: EventLog;
strNames: stringarray;
begin
c:= 0;
eventlogs:= EventLog.GetEventLogs(computername);
// Resize the array to number of eventlog names
SetLength(strNames, High(eventlogs)+1);
// Loop through the eventlogs and get the names
for e in eventLogs do
begin
strNames[c]:= e.LogDisplayName;
c:= c + 1;
end;
result:= strNames;
end;
procedure TWinForm.TreeView1_AfterSelect(sender: System.Object; e: System.Windows.Forms.TreeViewEventArgs);
var
myTreeView: TreeView;
myNode: TreeNode;
myParentNode: TreeNode;
begin
if sender is TreeView then
begin
myTreeView:= sender as TreeView;
myNode:= myTreeView.SelectedNode;
if (myNode.Parent <> Nil) then
begin
myParentNode:= myTreeView.SelectedNode.Parent;
strSelEvtLogName:= myNode.Text;
strSelComputerName:= myParentNode.Text;
DisplayLogEntries(ListView1, strSelEvtLogName, strSelComputerName);
end
else
begin
ListView1.Items.Clear;
end;
end;
end;
procedure TWinForm.ListView1_SelectedIndexChanged(sender: System.Object; e: System.EventArgs);
var
myItem: ListViewItem;
mySubItem: ListViewItem.ListViewSubItem;
index: Integer;
begin
RichTextBox1.Clear;
for myItem in ListView1.SelectedItems do
begin
index:= myItem.Index;
//mySubItem:= myItem.SubItems.Item[7];
//index:= Convert.ToInt32(mySubItem.Text) - 1;
AppendLogMessage(RichTextBox1, strSelEvtLogName, strSelComputerName, index);
end;
end;
procedure TWinForm.TWinForm_Load(sender: System.Object; e: System.EventArgs);
begin
// Add information for the local computer
AddComputer(TreeView1, SystemInformation.ComputerName);
// Expand display
TreeView1.ExpandAll;
end;
The writing of an event to a log looks just as simple, although I haven't had the opportunity to play with that
yet.
Labels: .NET, Code, Delphi