问题
I have an EventLogReader object, and a query in the event log that looks like this:
string query = "*[System[(Level=2) and TimeCreated[@SystemTime>='%LastRun%']]]")
The code basically uses the reader to query for all the events that match the search query since the last time the reader was run.
I would rather use the EventBookmark for this purpose. That's what it is for, after all! But I am having trouble finding any working code.
My existing code run, in part, like this:
// This line replaces the %LastRun% code with the date
var myQuery = myEventLogQuery.Query.Replace("%LastRun%", myEventLogQuery.LastRun.ToString("o"));
var query = new EventLogQuery(myEventLogQuery.Log, myEventLogQuery.PathType, myQuery);
// Now set the LastRun date. I want to avoid this...
myEventLogQuery.LastRun = DateTime.UtcNow;
// ... by making this next line smarter.
var reader = new EventLogReader(query);
// var reader = new EventLogReader(query, ??? new EventBookmark());
EventRecord eventRecord;
while ((eventRecord = reader.ReadEvent()) != null)
{
EventRecords.Add(new EventRecordItem(eventRecord));
}
I should be able to use the EventBookmark property of the first (or last) EventRecord to restrict the next query, but I want to set the EventBookmark initially to be basically the highest record in the log.
When the application runs initially, I don't need it to tell me about all the event log entries from the past, I only care about ones that occur after the application starts.
回答1:
OK, I went ahead and experimented a lot, and managed to work out a good system for this. Since this topic isn't really covered, I'm posting my answer here. I hope it's useful!
First challenge is creating the initial EventBookmark. You can't just instantiate one. You need to derive one from an existing EventRecord. To do this, I query for the last item in the log and base my EventBookmark on that.
using System.Diagnostics.Eventing.Reader;
public class MyEventLogQuery
{
public string Log { get; set; }
public PathType PathType { get; set; }
public string Query { get; set; }
public EventBookmark Bookmark { get; set; }
public MyEventLogQuery(string log = "Application", PathType pathType = PathType.LogName, string query = "*[System[(Level=2)]]")
{
Log = log;
PathType = pathType;
Query = query;
Bookmark = GetBookmark(log, pathType); // Query is not important here
}
// This method returns the bookmark of the most recent event
// log EventRecord or null if the log is empty
private static EventBookmark GetBookmark(string log, PathType pathType)
{
var elq = new EventLogQuery(log, pathType) {ReverseDirection = true};
var reader = new EventLogReader(elq);
var record = reader.ReadEvent();
if (record != null)
return record.Bookmark;
return null;
}
}
Next step is to use the bookmark (or lack of bookmark) when subsequently querying the Event Log.
using System.Diagnostics.Eventing.Reader;
public class EventLogTracker()
{
public List<MyEventLogQuery> Queries { get; set; }
// ... snipped some stuff
public int Run()
{
var count = 0;
foreach (var myQuery in Queries)
{
var query = new EventLogQuery(myQuery.Log, myQuery.PathType, myQuery.Query);
// This is the important bit. Must take account that the
// log may have been empty, so bookmark could be null
var reader = myQuery.Bookmark != null ? new EventLogReader(query, myQuery.Bookmark) : new EventLogReader(query);
EventRecord eventRecord;
while ((eventRecord = reader.ReadEvent()) != null)
{
// Do stuff
// ...
// Then update the bookmark
myQuery.Bookmark = eventRecord.Bookmark;
count++;
}
}
return count;
}
And voila, you have code that uses the EventBookmark to only give you events that have occurred since the application was started.
来源:https://stackoverflow.com/questions/31509513/how-to-create-an-eventbookmark-when-querying-the-event-log