Reputation: 21
I'm building an application which should watch file for access, reading, writing, deleting.
I'm using the built in auditing system on a Windows 7 Pro. You turn it on in gpedit.msc, and then set the audit flags for the files you want to watch, and then you get entries in the security log.
What I want to do is watching the security log in real time, which I do like this:
static EventLog securityLog = new EventLog("Security", System.Environment.MachineName);
securityLog.EntryWritten += new EntryWrittenEventHandler(OnEntryWritten);
securityLog.EnableRaisingEvents = true;
This works and calls my OnEntryWritten
-Function.
public static void OnEntryWritten(object source, EntryWrittenEventArgs entry)
entry.Entry
is the EntryWrittenEventArgs.Entry
Property, which doesn't seem to give me any access to the XML-properties of the entry, which I need, beecause it contains additional information.
What I'm trying to do afterwards is to query the event log via another EventLogReader
, because I can get entry.Entry.Index
which should be the eventInstance.RecordId
of an event that I get from the EventLogReader
.
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">">*[System[(EventRecordID=181616)]]</Select>
</Query>
</QueryList>
works as XPath query directly in the event log, it gives back just one entry.
string query = "*[System[(EventRecordID=" + entry.Entry.Index + ")]]";
// Create Event Log Query and Reader
EventLogQuery eventsQuery = new EventLogQuery("Security",
PathType.LogName,
query);
EventLogReader logReader = new EventLogReader(eventsQuery);
// For each event returned from the query
for (EventRecord eventInstance = logReader.ReadEvent(); eventInstance != null; eventInstance = logReader.ReadEvent())
{
if (eventInstance.RecordId == entry.Entry.Index) //RecordId and Index are the same thing: the identifier of the record/entry.
{
XDocument xml;
try
{
xml = XDocument.Parse(logReader.ReadEvent().ToXml());
}
catch (Exception e)
{
//logger.Write(e.Message.ToString());
break; //We seem to have a newline character in the logReader.ReadEvent() sometimes, but nothing else, so we can safely break here or completely ignore it.
}
This fails when I try to get the xml, why is that?
I get an "Object reference not set to an instance of an object." which is an System.NullReferenceException
. I'm not sure how this error actually can happen.
If I query the log like this
EventLogQuery eventsQuery = new EventLogQuery("Security",
PathType.LogName,
"*[EventData[Data[@Name='ObjectType'] and (Data='File')]] ");
it works without a problem.
What's the best way to do this, anyway?
Upvotes: 0
Views: 3206
Reputation: 1110
Every time you call ReadEvent() you are retrieving the next event. Your query only returns one event. The line
xml = XDocument.Parse(logReader.ReadEvent().ToXml());
is the culprit.
Your code should look more like this:
string query = "*[System[(EventRecordID=" + entry.Entry.Index + ")]]";
// Create Event Log Query and Reader
EventLogQuery eventsQuery = new EventLogQuery("Security",
PathType.LogName,
query);
EventLogReader logReader = new EventLogReader(eventsQuery);
EventRecord eventInstance = logReader.ReadEvent();
if (eventInstance != null)
{
XDocument xml;
try
{
xml = XDocument.Parse(eventInstance.ToXml());
}
catch (Exception e)
{
//This probably won't happen now.
break; //We seem to have a newline character in the
}
}
Upvotes: 0
Reputation: 11
The InstanceId does not return the same value as the index value.
Try the following snippet to get the correct ID
UInt16 eventid = (UInt16)(entry.Entry.InstanceId)
Upvotes: 1
Reputation: 223
Have you checked the output of XDocument.Parse(logReader.ReadEvent().ToXml())
? Does ToXml()
generate a proper XDocument (with header, root element...)? That might be the problem.
However if you don't stick to this solution, you could try to use FileSystemWatcher or the official file monitoring tool from Microsoft: Filemon
Upvotes: 0