urlreader
urlreader

Reputation: 6605

Subscription to Windows Event Log?

I'm working on a project that needs to check the Windows Event Log frequently for certain events. I'm wondering - is there a way to create a subscription to the Windows Event Log for certain events?

So, when the event happens (e.g. event id = 00001), I can get a notification in the code?

If this cannot be done, then I will have to keep searching the event log, which is not efficient.

Upvotes: 13

Views: 9391

Answers (2)

James Westgate
James Westgate

Reputation: 11444

Here is a simplified example, which uses the query generated in the XML tab on the filter view of the Windows Event Viewer. It loads the initial records returned by the query, then keeps watch for any future items.

var query = $"*[System[(EventID=1942) and TimeCreated[timediff(@SystemTime) <= 604800000]]]";
var decoded = System.Web.HttpUtility.HtmlDecode(query);
var eventLogQuery = new EventLogQuery("Application", PathType.LogName, decoded);
var watcher = new EventLogWatcher(eventLogQuery, null, true);
var count = 0;

watcher.EventRecordWritten += (object sender, EventRecordWrittenEventArgs e) =>
{
    count += 1;

    Console.WriteLine($"Found {count} items for query");
};

watcher.Enabled = true;

for (var i = 0; i < 5; i++)
{ 
    System.Threading.Thread.Sleep(10000);
}

Upvotes: 2

Elena Oblomova
Elena Oblomova

Reputation: 419

As you're using C#, I think you should use Windows API to subscribe to certain Windows events. You can do it by using either EventLogWatcher or EventLog class. You can find an example of creating a Windows Event Log subscription using EventLog on MSDN.

If you prefer EventLogWatcher, refer to its limited documentation.

And here is my example:

public static void subscribe()
{
    EventLogWatcher watcher = null;
    try
    {
        EventLogQuery subscriptionQuery = new EventLogQuery(
            "Security", PathType.LogName, "*[System/EventID=4624]");

        watcher = new EventLogWatcher(subscriptionQuery);

        // Make the watcher listen to the EventRecordWritten
        // events.  When this event happens, the callback method
        // (EventLogEventRead) is called.
        watcher.EventRecordWritten +=
            new EventHandler<EventRecordWrittenEventArgs>(
                EventLogEventRead);

        // Activate the subscription
        watcher.Enabled = true;

        for (int i = 0; i < 5; i++)
        {
            // Wait for events to occur. 
            System.Threading.Thread.Sleep(10000);
        }
    }
    catch (EventLogReadingException e)
    {
        Log("Error reading the log: {0}", e.Message);
    }
    finally
    {
        // Stop listening to events
        watcher.Enabled = false;

        if (watcher != null)
        {
            watcher.Dispose();
        }
    }
    Console.ReadKey();
}

// Callback method that gets executed when an event is
// reported to the subscription.
public static void EventLogEventRead(object obj,
    EventRecordWrittenEventArgs arg)
{
    // Make sure there was no error reading the event.
    if (arg.EventRecord != null)
    {
        //////
        // This section creates a list of XPath reference strings to select
        // the properties that we want to display
        // In this example, we will extract the User, TimeCreated, EventID and EventRecordID
        //////
        // Array of strings containing XPath references
        String[] xPathRefs = new String[9];
        xPathRefs[0] = "Event/System/TimeCreated/@SystemTime";
        xPathRefs[1] = "Event/System/Computer";
        xPathRefs[2] = "Event/EventData/Data[@Name=\"TargetUserName\"]";
        xPathRefs[3] = "Event/EventData/Data[@Name=\"TargetDomainName\"]";

        // Place those strings in an IEnumerable object
        IEnumerable<String> xPathEnum = xPathRefs;

        // Create the property selection context using the XPath reference
        EventLogPropertySelector logPropertyContext = new EventLogPropertySelector(xPathEnum);

        IList<object> logEventProps = ((EventLogRecord)arg.EventRecord).GetPropertyValues(logPropertyContext);
        Log("Time: ", logEventProps[0]);
        Log("Computer: ", logEventProps[1]);
        Log("TargetUserName: ", logEventProps[2]);
        Log("TargetDomainName: ", logEventProps[3]);
        Log("---------------------------------------");

        Log("Description: ", arg.EventRecord.FormatDescription());
    }
    else
    {
        Log("The event instance was null.");
    }
}

Upvotes: 27

Related Questions