我需要能够检索Hyper-V的事件日志条目,作为我们使用的监控系统的一部分。目前我使用VBScript和WMI并执行以下操作:
query = "Select * from Win32_NTLogEvent where LogFile = 'System' and TimeGenerated >= '" & last_check & "'"
set wmi_objectset = wmi_service.ExecQuery(query, "WQL", &h30)
这可以正常工作,但它只检索一些Hyper-V日志而不是全部。一些谷歌搜索表明没有办法解决这个问题,MS没有能力将所有Hyper-V日志读入WMI。所以我需要一种不同的方法。
更多Googling发现了一些用于读取事件日志的C#代码,这样做会很好,因为我很乐意使用C#而不是VBScript。麻烦的是,虽然我可以阅读标准日志,如 System 和 Application ,但我无法解读如何阅读我想要的Hyper-V日志。代码如下:
eventLog = new EventLog();
eventLog.Log = eventLogName;
foreach (EventLogEntry log in eventLog.Entries)
{
如果我将 eventLogName 设置为" System"然后它工作并读回所有日志条目(并且它的速度非常快)。但我需要的是日志 Microsoft-Windows-Hyper-V-VMMS-Admin 中的条目。如果我将 eventLogName 设置为" Microsoft-Windows-Hyper-V-VMMS-Admin"我得到一个例外:
Unhandled Exception: System.InvalidOperationException: The event log 'Microsoft-Windows-Hyper-V-VMMS-Admin' on computer '.' does not exist.
日志确实存在,并且PowerShell命令:
Get-WinEvent -LogName Microsoft-Windows-Hyper-V-VMMS-Admin
检索事件,因此问题可能只是指定EventLog对象的日志名称的正确方法。
所以我的问题只是在我的C#程序中使用什么来获取Hyper-V VMMS管理日志中的条目。
我正在测试的服务器是2012R2,但我不认为问题与Windows的确切版本有关。还有其他获取日志数据的方法,比如Get-WinEvent或wevtutil,但我更希望让C#程序工作,使用替代方法将是最后的手段。
答案 0 :(得分:1)
这是因为System.Diagnostics.EventLog
仅支持“旧式”事件日志。 “新样式”事件日志是您在“应用程序和服务日志”下的事件查看器中看到的(然后是其中的子文件夹,而不是直接在其中的子文件夹),并且它不支持读取它们。要阅读这些内容,您需要使用System.Diagnostics.Eventing.Reader
中提供的类。请注意,它们具有不同的界面,更适合实时事件检索。示例代码:
using (var reader = new EventLogReader("Microsoft-Windows-Hyper-V-VMMS-Admin")) {
EventRecord eventRecord;
while ((eventRecord = reader.ReadEvent()) != null) {
Console.WriteLine("{0:s} {1}", eventRecord.TimeCreated, eventRecord.FormatDescription());
}
}
如果您对最新事件特别感兴趣,则以相反的顺序查询它们并以这种方式过滤它们会更有效。使用一个小枚举器助手,我们可以使用LINQ:
IEnumerable<EventRecord> ReadEventsReverse(string logName) {
using (
var reader = new EventLogReader(
new EventLogQuery(logName, PathType.LogName) { ReverseDirection = true }
)
) {
EventRecord eventRecord;
while ((eventRecord = reader.ReadEvent()) != null) {
yield return eventRecord;
}
}
}
然后
var reverseEvents = ReadEventsReverse("Microsoft-Windows-Hyper-V-VMMS-Admin");
var reverseEventsToday = reverseEvents.TakeWhile(e => e.TimeCreated >= DateTime.Now.Date);
foreach (var eventRecord in reverseEventsToday) {
Console.WriteLine("{0:s} {1}", eventRecord.TimeCreated, eventRecord.FormatDescription());
}
如果您对阅读新活动特别感兴趣,使用the overload可以提供bookmark更高效,这样您就不会不断重读和过滤旧事件。