Reputation: 6605
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
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
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