HansM
HansM

Reputation: 21

How do I watch the event log for a specific entry in realtime, also getting the XML data?

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

Answers (3)

dylanT
dylanT

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

Leslie Jordaan
Leslie Jordaan

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

dave
dave

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

Related Questions