在一段时间内检查事件日志中是否记录了事件的最简单方法是什么?
我想执行一系列自动化测试步骤,然后检查是否有任何错误记录到应用程序事件日志中,忽略了一些我不感兴趣的来源。我可以使用System.Diagnostics.EventLog然后查看在Entries集合中,但它似乎对这种情况不太有用。例如,如果事件日志正在删除旧条目,则Entries.Count会随着时间的推移变小。我更喜欢某种方式来查询日志或监视它在一段时间内的变化。例如
DateTime start = DateTime.Now;
// do some stuff...
foreach(EventLogEntry entry in CleverSolution.EventLogEntriesSince(start, "Application"))
{
// Now I can do stuff with entry, or ignore if its Source is one
// that I don't care about.
// ...
}
答案 0 :(得分:5)
只是成为一名优秀的维基公民并努力完成,还有其他方法。我之前没有提出过建议,因为它只是作为测试套件的一部分在内部运行的东西完全矫枉过正,你在标题中说你想要的东西很简单。
但如果您需要查看运输代码中发生的事件,请继续阅读。信不信由你现在有三个不同的Windows API。
此类事物的原始API称为NotifyChangeEventLog(),从Windows 2000开始支持它。基本上,您使用WIN32 event log APIs打开事件日志,然后使用句柄调用此API你是由其他API和事件句柄给出的。当有新的事件日志条目要查看时,Windows将发出事件信号。
我自己从未使用过这个API,因为我最感兴趣的是远程事件日志访问,而这个API明确地不支持远程日志。但是,如果您拥有正确的权限,则属于的的其余API集允许您按顺序读取远程日志。
第二种方法是使用Windows Management Instrumentation API,这确实支持本地和远程日志。这是一个基于COM / DCOM的API,已在Windows中存在多年,.NET Framework在System.Management命名空间中有很好的实现。基本上你要做的是创建一个EventQuery来查找Win32_NTLogEvent类型(在WMI类型系统中)的新WMI对象的外观。这些内容将显示新的事件日志条目,它们将实时呈现。这些对象上的属性包含日志条目的所有详细信息。有一个article from MSDN magazine谈论在Visual Studio中使用这些东西。
同样,对于测试应用程序来说,这将是完全过度的,它将需要比现有解决方案更多的代码。但是几年前我为网络管理应用程序编写了一个子系统,该子系统使用此API的DCOM风格从网络上的所有服务器收集事件日志,以便我们可以对特定的服务器发出警报。它非常光滑,接近实时。如果您使用DCOM在C ++中实现此功能,请准备好处理多线程公寓和许多毛茸茸的逻辑,以检测您与远程服务器的连接是否/何时上升或下降。
Windows Vista(和Server 2008)有一个与事件记录和跟踪相关的全新API套件。 new event log is documented here。subscribe to events。看起来有一个名为EvtSubscribe的API允许您{{3}}。我没有使用过这个API,所以我不能评论它的优缺点。
答案 1 :(得分:3)
话虽如此,这里的答案实际上应该非常简单,即使对于您的测试应用程序也是如此。
您需要在开始测试之前打开EventLog,并为EventLog.EntryWritten事件订阅事件处理程序。这是.NET公开NotifyChangeEventLog()Win32 API的方式。
将当前逻辑从GetEventLogEntriesSince()
移动到事件处理程序中,但不是将事件添加到列表中以进行返回,而是将它们存储在可以从运行结束时的某个位置检索的列表中。您可以通过其Entry属性从EntryWrittenEventArgs参数中检索日志条目的内容。
答案 2 :(得分:1)
System.Diagnostics.EventLog课程确实是这样做的正确方法。
您的主要异议似乎是日志可以在某些情况下删除旧条目。但是你说这是在软件测试场景中。您是否可以安排配置测试系统,使日志足够大以包含所有条目,并且在测试期间不会删除旧条目?
答案 3 :(得分:0)
我提出的解决方案确实使用System.Diagnostics.EventLog并简单地迭代所有事件以过滤我想要的那些事件。我想这很简单,我只是觉得会有更高效的界面。任何建议或改进都非常欢迎!
我创建了一个从某个时间开始返回事件日志条目的方法:
/// <summary>
/// Steps through each of the entries in the specified event log and returns any that were written
/// after the given point in time.
/// </summary>
/// <param name="logName">The event log to inspect, eg "Application"</param>
/// <param name="writtenSince">The point in time to return entries from</param>
/// <param name="type">The type of entry to return, or null for all entry types</param>
/// <returns>A list of all entries of interest, which may be empty if there were none in the event log.</returns>
public List<EventLogEntry> GetEventLogEntriesSince(string logName, DateTime writtenSince, EventLogEntryType type)
{
List<EventLogEntry> results = new List<EventLogEntry>();
EventLog eventLog = new System.Diagnostics.EventLog(logName);
foreach (EventLogEntry entry in eventLog.Entries)
{
if (entry.TimeWritten > writtenSince && (type==null || entry.EntryType == type))
results.Add(entry);
}
return results;
}
在我的测试类中,我存储了一个时间戳:
private DateTime whenLastEventLogEntryWritten;
在测试设置期间,我将时间戳设置为写入最后一个事件日志条目的时间:
EventLog eventLog = new EventLog("Application");
whenLastEventLogEntryWritten = eventLog.Entries.Count > 0 ?
eventLog.Entries[eventLog.Entries.Count - 1] : DateTime.Now;
在测试结束时,我检查没有事件日志错误:
Assert.IsEmpty(GetEventLogEntriesSince("Application",
whenLastEventLogEntryWritten,
EventLogEntryType.Error),
"Application Event Log errors occurred during test execution.");
答案 4 :(得分:0)
我使用此Powershell在过去7天内扫描事件日志中的相关条目:
$d=Get-Date
$recent=[System.Management.ManagementDateTimeConverter]::ToDMTFDateTime($d.AddDays(-7))
get-wmiobject -computer HOSTNAME -class Win32_NTLogEvent `
-filter "logfile = 'Application' and (sourcename = 'SOURCENAME' or sourcename like 'OTHERSOURCENAME%') and (type = 'error' or type = 'warning') AND (TimeGenerated >='$recent')" |
sort-object @{ expression = {$_.TimeWritten} } -descending |
select SourceName, Message |
format-table @{Expression = { $_.SourceName};Width = 20;Label="SourceName"}, Message
如果您使用C#(已标记,但未在问题中提及),则神奇之处在于get-wmiobject查询。