Click here to Skip to main content
13,902,633 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

14.6K views
18 bookmarked
Posted 8 Feb 2016
Licenced Ms-PL

Top 9 Windows Event Log Tips Using C#

, 8 Feb 2016
Rate this:
Please Sign up or sign in to vote.
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.

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

Event Viewer is a tool that displays detailed information about significant events (for example, programs that don't start as expected or updates that are downloaded automatically) on your computer. Event Viewer can be helpful when troubleshooting problems and errors with Windows and other programs.

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
// 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.

 
It is a piece of cake to configure log4net to start logging messages to specified event log. You need the following information in your app.config or log4net.config
 
<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.

Write to Event Log NLog

Definition

NLog is a free logging platform for .NET, Silverlight and Windows Phone with rich log routing and management capabilities. NLog makes it easy to produce and manage high-quality logs for your application regardless of its size or complexity.
 
To start using NLog, first you need to install two NuGet packages- NLog and NLog.Config. The later is going to add the NLog.config file to your project. The below configuration will set up the logger to write the new messages to the specified event log.
 
<?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.

 
If you enjoy my publications, feel free to SUBSCRIBE
Also, hit these share buttons. Thank you!
 

All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Anton Angelov
CEO Automate The Planet
Bulgaria Bulgaria
Anton Angelov is an IT Consultant and Quality Assurance Architect at Innovative Lab. He is passionate about automation testing and designing test harness and tools, having the best industry development practices in mind. In addition, he is an active blogger and the founder of Automate The Planet. He strives to make the site one of the leading authorities in Automation Testing by presenting compelling articles, inspiring ardent discussions amongst the community. He is also one of the most-rated-answer authors of questions about Test Automation Frameworks (WebDriver) on Stack Overflow.

You may also be interested in...

Pro

Comments and Discussions

 
Suggestionreading the event log(s)... Pin
John Torjo9-Feb-16 9:24
professionalJohn Torjo9-Feb-16 9:24 
QuestionWhen to use? Pin
Rob Philpott8-Feb-16 1:07
memberRob Philpott8-Feb-16 1:07 
AnswerRe: When to use? Pin
Slacker0078-Feb-16 5:42
professionalSlacker0078-Feb-16 5:42 
GeneralRe: When to use? Pin
Anton Angelov8-Feb-16 8:10
memberAnton Angelov8-Feb-16 8:10 
QuestionImages and scripts won't show Pin
Volkan Paksoy7-Feb-16 23:24
memberVolkan Paksoy7-Feb-16 23:24 
AnswerRe: Images and scripts won't show Pin
Anton Angelov8-Feb-16 3:57
memberAnton Angelov8-Feb-16 3:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190306.1 | Last Updated 8 Feb 2016
Article Copyright 2016 by Anton Angelov
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid