views:

1407

answers:

2

I have the following code in both a C# console app and a C# windows service. It works in the console app. It picks up the specified event, and calls MatchEvent() correctly. The same code in a C# windows service does not pick up the same specified event, it never sees it, but sees the other events. The event in question is written to the Application log, so I am not trying to read the Security log.

I figured it was an account permissions issue (the service was running as LocalSystem). I changed the service to use the same account I was running the consoleapp as, and I still see the same behaviour. I verified that there wasn't anything done with GP or custom registry to change permissions (it's a fresh installed OS) and the account used with both apps is a localadmin.

Is there something I am missing? I researched EventLogPermission as well, but that does not seem to apply, since I am getting events out of the eventLog.

The code:

private void WatchLogs()
{
    try
    {
        _eventLogs = EventLog.GetEventLogs();

        foreach (EventLog eventLog in _eventLogs)
        {
            if (eventLog.LogDisplayName.Contains("Security"))
            {
                _logger.DebugFormat(string.Format("{0}: not watching", eventLog.LogDisplayName));
            }
            else
            {
                eventLog.EntryWritten += EventLogEntryWritten;
                eventLog.EnableRaisingEvents = true;

                if (_logger.IsInfoEnabled)
                {
                    _logger.InfoFormat("Monitoring: {0} | Raising Events: {1}", eventLog.LogDisplayName,
                                       eventLog.EnableRaisingEvents);
                }
            }
        }
    }
    catch (Win32Exception ee)
    {
        _logger.DebugFormat(string.Format("{0}: not watching({1})", eventLog.LogDisplayName, ee.Message));
    }
    catch (SecurityException securityException)
    {
        _logger.ErrorFormat("Error accessing eventlog: {0} : {1}", eventLog.LogDisplayName, securityException.Message);
    }
}

private void EventLogEntryWritten(object sender, EntryWrittenEventArgs currentEvent)
{
  var log = (EventLog) sender;

  if (_logger.IsDebugEnabled)
    _logger.DebugFormat(
      "Event Raised: |Log:{0}|Source:{1}|EventID:{2}|",log.LogDisplayName,
        currentEvent.Entry.Source,currentEvent.Entry.EventID);

  MatchEvent(currentEvent);
}
A: 

Been messing around with this off and on. It seems, although I still not 100 percent sure, that the following are happening:

  • The events are cluster events, and so may be written from either node to the local system, but the EventLog class only picks up events writtern locally.
  • The system responds to the WriteEntry() method only if the last write event occured at least six seconds perviosuly. The events I were looking for happened within seconds of each other, and were swamped by other related, but not important events.

Any confirmation of this would be helpful. Info obtained here: msdn

James Pogran
A: 

Yes you miss events if they happen within the polling inteval. You can use WMI (through System.Management) to alter the polling interval. This is an older article, but it will give you the information you need to do this. See the section on Management Events.

You will also want to perform your WriteEntry (if you are writing to the event log as well) on a separate thread, so you aren't blocking receiving events.

Richard Hein
if re-written, could this 'subscribe" to the eventlog like the .NET class does?
James Pogran
Yes, absolutely. You will have to do a bit of reading on Management Events in WMI. The Server Explorer in VS 2008 (maybe in 2005 too, but I can't remember) has a WMI node. You can right-click on those to get options for generating code, and some dialogs that will help you sent up event handlers etc.... All that functionality used to be in a separate downloadable addin from MS. I haven't used it lately - the built in version, but it's basically the same. Check out the link to the article to see what I mean.
Richard Hein