Top 9 Windows Event Log Tips Using C#






4.92/5 (6 votes)
Learn how to use the Windows Event Log via C#. Find different logging solutions and various test strategies.The post Top 9 Windows Event Log Tips Using C# appeared first on Automate The Planet.
Introduction
In this article, I am going to share with you my tips and tricks on how to use Windows Event Log with C#. You will find some basic examples to get you started. After that in the publication, you will read about how to create Event Loggers through prominent logging libraries like log4net and NLog. At the end of the article, I am going to show you how to create unit and integration tests for your event log loggers.
Getting Started Event Log C#
Definition
To start writing messages to the Event Log, you first need to create a new event source.
Create Event Source
if (!EventLog.SourceExists("Automate The Planet"))
{
EventLog.CreateEventSource("Rock'N'Roll", "Automate The Planet");
}
The code first checks if the event source exists if it doesn't, it is created.

Write New Event Log Entry
EventLog eventLog = new EventLog();
eventLog.Source = "Automate The Planet";
// Write a new entry to the source.
eventLog.WriteEntry("You need community. It’s here and it’s waiting just for you. ",
EventLogEntryType.Information);
Create a new log instance and assign its source instance. Then call the WriteEntry method.

Read Event Log Entries
EventLog automateThePlanetLog = new EventLog();
automateThePlanetLog.Log = "Automate The Planet";
foreach (EventLogEntry entry in automateThePlanetLog.Entries)
{
Console.WriteLine(entry.Message);
}
The above code reads all the entries from the log named "Automate The Planet". The entry object contains all the information about the log entry,
// Delete Event Source if exists.
if (EventLog.SourceExists("Rock'N'Roll"))
{
EventLog.DeleteEventSource("Rock'N'Roll");
}
// Delete the Log
if (EventLog.Exists("Automate The Planet"))
{
// Delete Source
EventLog.Delete("Automate The Planet");
}
If the event log source exists then, we delete it. The same is valid for the event log.
Write to Event Log log4net
Definition
The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets. log4net is a port of the excellent Apache log4j™ framework to the Microsoft® .NET runtime.
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net debug="true">
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<param name="LogName" value="Kaspersky Event Log" />
<param name="ApplicationName" value="kis" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="EventLogAppender" />
</root>
</log4net>
Set the LogName parameter to be equal to the name of the event log where your code needs to write. The ApplicationName should be set to the name of the event log source.
private static readonly log4net.ILog log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
static void Main(string[] args)
{
log.Info("log4net log message to Kaspersky event log.");
}
The above code is going to write the specified message in the 'Kaspersky Event Log' event log with source kis.
Definition
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log" >
<targets>
<target
name="eventlog"
xsi:type="EventLog"
layout="${longdate}|${level}|${message}"
log="Kaspersky Event Log"
source="kis"
machineName="." />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="eventlog" />
</rules>
</nlog>
The below code is going to write the specified message to the Kaspersky Event Log.
private static Logger logger = LogManager.GetCurrentClassLogger();
public static void Main(string[] args)
{
logger.Info("NLog log message to Kaspersky event log.");
}
Unit Test Event Log Logger
To be able to exchange the logger solutions if needed, we can create a logger interface that is going to be used in the production code.
public interface ILogger
{
void LogInfo(string message);
void LogError(Exception exception);
}
After that we can create a concrete logger implementation that depends on NLog.
public class EventLogger : ILogger
{
private readonly Logger logger = LogManager.GetCurrentClassLogger();
public void LogInfo(string message)
{
if (string.IsNullOrEmpty(message))
{
throw new ArgumentException("The logged message cannot be null or empty.");
}
logger.Log(LogLevel.Info, message);
}
public void LogError(Exception exception)
{
logger.Log(LogLevel.Error, exception.Message);
}
}
Let's assume that we need to create a calculation application. Before the calculation, a new message should be written to the event log.
public class Calculator
{
private readonly ILogger logger;
public Calculator(ILogger logger)
{
this.logger = logger;
}
public int Sum(int a, int b)
{
logger.LogInfo(string.Format("Sum {0} and {1}", a, b));
return a + b;
}
}
As you can see the Calculator is not using the EventLogger directly but is working with the ILogger interface. We can use unity IOC container to initialize the calculator app and the logger.
public static void Main(string[] args)
{
// Register a type to have a singleton lifetime without mapping the type
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<Loggers.ILogger, EventLogger>(
new ContainerControlledLifetimeManager());
Loggers.ILogger eventLogger = unityContainer.Resolve<Loggers.ILogger>();
eventLogger.LogInfo("EventLogger log message to Kaspersky event log.");
}
If you need to write unit tests for the Calculator, it is really easy to mock the EventLogger. For a mocking framework, I use Telerik Just Mock. You can install it as a NuGet package. The Lite version is free.
[TestClass]
public class CalculatorShould
{
[TestMethod]
public void LogMessageWhenSumNumbers()
{
//Arrange
var logger = Mock.Create<ILogger>();
string loggedMessage = string.Empty;
Mock.Arrange(() => logger.LogInfo(Arg.AnyString)).
DoInstead(() => loggedMessage = "Automate The Planet rocks!");
Calculator calculator = new Calculator(logger);
//Act
calculator.Sum(1, 1);
//Assert
Assert.AreEqual<string>("Automate The Planet rocks!", loggedMessage);
}
}
As the calculator app uses an interface instead of the EventLogger directly, it is easy to mock its behaviour. Instead of sending the specified message to the event log, we set the loggedMessage variable. If the LogInfo method is called the variable is initialized. At the end of the test assert that the correct string is assigned.
Integration Test Event Log Logger
Sometimes you need to test the real integration between the event log and your application. If you develop a web application, it may be deployed on multiple machines so you should be able to test against all of them.
public abstract class EventLogAsserter
{
private readonly string logName;
private readonly List<string> machineNames;
private readonly List<EventLog> eventLogs;
private readonly List<EventLogEntry> revertedEventLogEntries;
public EventLogAsserter(string logName, List<string> machineNames)
{
this.logName = logName;
this.machineNames = machineNames;
this.eventLogs = new List<EventLog>();
this.revertedEventLogEntries = new List<EventLogEntry>();
}
public void AssertMessageExistsInTop(string message, string sourceName, int topCount)
{
bool isMessagePresent = false;
this.InitializeEventLogs(sourceName);
for (int i = 0; i < topCount; i++)
{
if (this.revertedEventLogEntries.Count > i)
{
var currentEntry = revertedEventLogEntries[i];
if (currentEntry.Message.Contains(message))
{
isMessagePresent = true;
break;
}
}
else
{
break;
}
}
Assert.IsTrue(isMessagePresent,
"The event log '{0}' doesn't contain the message '{1}'",
this.logName,
message);
}
private void InitializeEventLogs(string sourceName)
{
this.eventLogs.Clear();
this.revertedEventLogEntries.Clear();
foreach (var currentMachine in this.machineNames)
{
try
{
var currentEventLog = new EventLog(this.logName, currentMachine, sourceName);
this.eventLogs.Add(currentEventLog);
var eventLogEntries = new EventLogEntry[currentEventLog.Entries.Count];
currentEventLog.Entries.CopyTo(eventLogEntries, 0);
this.revertedEventLogEntries.AddRange(eventLogEntries.Reverse().ToList());
}
catch (InvalidOperationException ex)
{
string eventLogNotFoundExceptionMessage =
string.Format("The specified event log- '{0}' doesn't exist on machine- '{1}'",
this.logName,
currentMachine);
throw new NonExistingEventLogException(eventLogNotFoundExceptionMessage, ex);
}
}
}
}
This is the base class for the specific event logs asserters. It is going to get the event log entries from the specified event log from all mentioned machines. The log entries are populated reverted so that you can check the newest first. Through the public method AssertMessageExistsInTop, you can check if a particular message exists in the last topCount messages in the event log.
public class AntonMachineEventLogAsserter : EventLogAsserter
{
public AntonMachineEventLogAsserter()
: base("Application", new List<string>() { "DESKTOP-FL88834" })
{
}
}
The specific loggers inherit the EventLogAssert and pass to its constructor the name of the event log and the list of machines' names.
The usage is pretty straightforward.
AntonMachineEventLogAsserter eventLogAsserter = new AntonMachineEventLogAsserter();
eventLogAsserter.AssertMessageExistsInTop(
"The VSS service is shutting down due to idle timeout.", "VSS", 22);
Test Manually Remote Machines' Event Logs
Open the Event Viewer. Click on the Action menu item and choose Connect to another Computer. You need to be added as an administrator of the remote machine.

So Far in the C# Series
1. Implement Copy Paste C# Code
2. MSBuild TCP IP Logger C# Code
3. Windows Registry Read Write C# Code
4. Change .config File at Runtime C# Code
5. Generic Properties Validator C# Code
6. Reduced AutoMapper- Auto-Map Objects 180% Faster
7. 7 New Cool Features in C# 6.0
8. Types Of Code Coverage- Examples In C#
9. MSTest Rerun Failed Tests Through MSTest.exe Wrapper Application
10. Hints For Arranging Usings in Visual Studio Efficiently
11. 19 Must-Know Visual Studio Keyboard Shortcuts – Part 1
12. 19 Must-Know Visual Studio Keyboard Shortcuts – Part 2
13. Specify Assembly References Based On Build Configuration in Visual Studio
14. Top 15 Underutilized Features of .NET
15. Top 15 Underutilized Features of .NET Part 2
16. Neat Tricks for Effortlessly Format Currency in C#
17. Assert DateTime the Right Way MSTest NUnit C# Code
18. Which Works Faster- Null Coalescing Operator or GetValueOrDefault or Conditional Operator
19. Specification-based Test Design Techniques for Enhancing Unit Tests
20. Get Property Names Using Lambda Expressions in C#
- log4net Complete Guide
- NLog Complete Guide
- Working With EventViewer Using C# For Beginners
- Reading and Clearing a Windows Event Log with C# .NET
- .NET Logging Tools and Libraries
All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement