我正在开发一个显示事件日志数据的Web应用程序,类似于事件查看器。该应用程序还必须为用户提供一种方式,以便在使用Web服务将条目写入订阅日志时订阅事件日志并接收通知。
我正在使用此代码订阅Web服务中的事件日志:
EventLog eventLog = new EventLog(observer.logName, observer.machineName);
eventLog.EnableRaisingEvents = true;
eventLog.EntryWritten += new EntryWrittenEventHandler(eventLog_EntryWritten);
eventList.Add(eventLog);
我正在尝试使用观察者作为事件日志的订阅者,并且在处理EventWritten事件时,调用一个观察者的Update方法。问题是,我不知道如何区分事件日志,因为它们都使用相同的事件处理程序。我这样做是因为事件日志的数量因机器而异。此外,我希望观察者只处理一种类型的EventLog,即。当一个事件写入应用程序日志时,一个观察者会发送一封电子邮件。
我使用这行代码获取当前计算机上的所有日志:
remoteEventLogs = EventLog.GetEventLogs(machineName);
EventWritten事件处理程序具有此对象发送者参数,但Visual Studio将其类型显示为EventLogInternal,我无法使用,并且我无法将发送者强制转换为EventLog以获取EventLog.Log属性。如果我尝试投射它,就像这样:
void eventLog_EntryWritten(object sender, EntryWrittenEventArgs e)
{
var log = (EventLog)sender;
}
我得到一个例外,说我不能将EventLogInternal转换为EventLog。
有没有办法知道哪个EventLog会触发事件?
由于
答案 0 :(得分:4)
我认为问题在于,EventLog
类的整个概念是它假设它在单个Log上运行 - 它就是这样做的。因此,EventWrittenEventArgs
和EventEntry
类都不包含包含Log-name的成员,因为它是由关联的EventLog-instance隐式赋予的。当然,糟糕的是,你无法在EventWritten-handler中找到它。
您可以围绕System.Diagnostics.EventLog
创建一个包装器,如下所示:
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
}
}
然后在通常使用MyEventLog
的地方使用EventLog
。可能会给它一个更好的名字。
您还可以通过提供从Action<string, EntryWrittenEventArgs>
内部调用的MyEventLog_EntryWritten
属性来分解“您的代码”部分,并且可以将其设置为“外部”处理函数。
答案 1 :(得分:3)
另一种选择是沿着这些方向使用反射:
string log = (string)sender.GetType().GetProperty("Log").GetValue(sender, null);
因为在这种情况下sender
实际上具有Log
属性。
答案 2 :(得分:2)
我认为您正在寻找的内容可以在EntryWrittenEventArgs中找到。
MSDN显示有一个名为Entry的属性,它向您显示有关刚刚记录的内容的各种信息。在EventLogEntry类中有一些可能对您有帮助的属性,例如MachineName或UserName。
这是Args类的链接 http://msdn.microsoft.com/en-us/library/system.diagnostics.entrywritteneventargs.aspx
这是Entry类的链接 http://msdn.microsoft.com/en-us/library/system.diagnostics.eventlogentry.aspx
我没有看到指向特定事件日志的直接链接,但如果您使用调试器在该类中查找,则Entry对象可能会为您提供足够的信息来查找它。
我希望这会有所帮助。
答案 3 :(得分:0)
我同意按照Christian的建议将EventLog类包装在另一个类中的想法。我最近研究过这样的要求。
这是我创建的课程
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);
}
}
这是用法
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);
}
}
答案 4 :(得分:0)
另一种选择是像这样更改事件注册:
eventLog.EntryWritten += (sender, e) => eventLog_EntryWritten(eventLog, e);