2011-05-18 20 views
5

Estoy trabajando en una aplicación web que muestra datos de registros de eventos, similar al Visor de eventos. La aplicación también debe proporcionar una forma para que los usuarios se suscriban a los registros de eventos y reciban notificaciones cuando se escribe una entrada en los registros suscritos, utilizando un servicio web.¿Hay alguna forma de saber qué EventLog provocó el evento EntryWritten en C#?

Estoy usando este código para suscribirse a un registro de eventos en el servicio web:

EventLog eventLog = new EventLog(observer.logName, observer.machineName); 
eventLog.EnableRaisingEvents = true; 
eventLog.EntryWritten += new EntryWrittenEventHandler(eventLog_EntryWritten); 
eventList.Add(eventLog); 

Estoy tratando de utilizar observadores como suscriptores a los registros de eventos, y cuando se maneja un evento EventWritten, llamada el método de actualización de un observador. El problema es que no sé cómo diferenciar los registros de eventos, ya que todos usan el mismo controlador de eventos. Estoy haciendo esto porque la cantidad de registros de eventos difiere de una máquina a otra. Además, quiero que los observadores manejen solo un tipo de EventLog, es decir. un observador enviaría un correo electrónico cuando un evento se escribe en el registro de la aplicación.

que utilizan esta línea de código para obtener todos los registros en el equipo actual:

remoteEventLogs = EventLog.GetEventLogs(machineName); 

EventWritten controlador de eventos tiene este parámetro object sender, pero Visual Studio muestra su tipo que EventLogInternal, que no puedo usar , y no puedo convertir el remitente a EventLog para obtener la propiedad EventLog.Log. Si trato de su emisión, así:

void eventLog_EntryWritten(object sender, EntryWrittenEventArgs e) 
    { 
     var log = (EventLog)sender; 
    } 

consigo una excepción diciendo que no puedo emitir un EventLogInternal a EventLog.

¿Hay alguna manera de saber qué EventLog dispara el evento?

Gracias

Respuesta

3

Otra opción sería la de utilizar la reflexión a lo largo de estas líneas:

string log = (string)sender.GetType().GetProperty("Log").GetValue(sender, null); 

desde sender en este caso, en realidad tiene la propiedad Log.

+0

nice hackear temporalmente. podría ser un problema con el nuevo .Net framework – Zam

2

Creo que lo que está buscando se pueden encontrar en las EntryWrittenEventArgs.

MSDN muestra que hay una propiedad llamada Entrada que le muestra todo tipo de información sobre lo que acaba de registrar. Hay algunas propiedades que pueden ayudarlo en la clase EventLogEntry, como MachineName o UserName.

Aquí hay un enlace a la clase Args http://msdn.microsoft.com/en-us/library/system.diagnostics.entrywritteneventargs.aspx

Aquí hay un enlace a la clase de entrada http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogentry.aspx

no veo un enlace directo con el registro de eventos específicos, pero si te asomas Alrededor de esa clase con el depurador, el objeto Entry podría darle suficiente información para buscarlo.

Espero que esto ayude a algunos.

+0

Sí, el problema es, la propiedad de entrada no muestra información sobre el registro de lo que se está escribiendo a de cualquier manera. – markhan777

4

Creo que el problema es que todo el concepto de la clase EventLog es que supone que funciona en un único registro, lo que hace. Por lo tanto, ni la clase EventWrittenEventArgs ni la EventEntry tienen un miembro que contiene el nombre de registro, ya que está implícitamente dado por la instancia EventLog asociada. Lo malo es, por supuesto, que no puede acceder a él dentro del manejador de EventWritten.

Se puede crear una envoltura alrededor de System.Diagnostics.EventLog, así:

class MyEventLog : EventLog 
{ 
    public MyEventLog(string logName, string machineName) 
     : base(logName, machineName) 
    { 
     base.EnableRaisingEvents = true; 
     base.EntryWritten += MyEventLog_EntryWritten; 
    } 

    void MyEventLog_EntryWritten(object sender, EntryWrittenEventArgs e) 
    { 
     Console.WriteLine("Entry in {0} log.", base.Log); 

     // Your code 
    } 
} 

A continuación, utilice MyEventLog en lugares donde normalmente se utilice EventLog. Sin embargo, probablemente le dé un mejor nombre.

También podría factorizar la parte "Su código" proporcionando una propiedad Action<string, EntryWrittenEventArgs> que está siendo llamada desde el interior MyEventLog_EntryWritten y se puede establecer en su función de controlador "externo".

+0

No he pensado en hacer una envoltura alrededor de EventLog, lo intentaré. Muchas gracias – markhan777

+0

Esto no le permite acceder al nombre de registro desde el controlador de eventos o me falta algo. – driverobject

+0

'base.Log' le dará el nombre del registro. O puede almacenarlo en una variable miembro en el constructor y acceder desde dentro del controlador de eventos (que es una función miembro). –

0

Estoy de acuerdo con la idea de ajustar la clase EventLog dentro de otra clase según lo sugerido por Christian. Recientemente trabajé en tal requisito.

Esta es la clase que he creado

public class EventLogWatcher : EventLog 
{ 
    Action<string, EntryWrittenEventArgs> _changeHandler; 
    public EventLogWatcher(string logName, Action<string, EntryWrittenEventArgs> changeHandler) 
     : base(logName) 
    { 
     _changeHandler = changeHandler; 
    } 

    public void EnableCapture() 
    { 
     base.EnableRaisingEvents = true; 
     base.EntryWritten += EventLogChangeHandler; 
    } 

    public void DisableCapture() 
    { 
     base.EnableRaisingEvents = false; 
     base.EntryWritten -= EventLogChangeHandler; 
    } 

    private void EventLogChangeHandler(object sender, EntryWrittenEventArgs e) 
    { 
     _changeHandler(base.Log, e); 
    } 
} 

Aquí es un uso

foreach (string eventlogType in LogTypes) 
      logWatchers.Add(new EventLogWatcher(eventlogType, EventLogChangeHandler)); 

     foreach (EventLogWatcher localLog in logWatchers) 
     { 
      try 
      { 
       localLog.EnableCapture(); 
      } 
      catch(Exception ex) 
      { 
       EventManager.PublishExceptionLogMessage(ex); 
      } 
     } 
     EventManager.PublishInfoLogMessage($"Started EventLog listeners for {string.Join(",", LogTypes)} logs"); 

private void EventLogChangeHandler(string eventLogType, EntryWrittenEventArgs e) 
    { 
     try 
     { 
      if (UploadAllowed(eventLogType, e)) 
      { 

       Dm.EventLog model = _eventLogEntryMapper.MapEntryToModel(e); 
       Task.Factory.StartNew(
         () => _eventLogUploadService.UploadEventLog(model), 
         _cancellationTokenProvider.Token, 
         TaskCreationOptions.None, 
         TaskScheduler.Default); 
      } 
     } 
     catch(Exception ex) 
     { 
      EventManager.PublishExceptionLogMessage(ex); 
     } 

    } 
Cuestiones relacionadas