如何使用WMI导出特定源的Windows事件日志?
我正在尝试使用Win32_NTEventLogFile
WMI类导出Windows事件日志的Applications
分支,但仅针对特定源过滤它。 (否则日志中包含太多不必要的信息。)
所以,举个例子,我需要导出包含MSSQL$SQLSRVR2012
所有记录:
我这样做:
using System.Management; static void Main(string[] args) { BackupEventLogFilterBySource("Application", "MSSQL$SQLSRVR2012", @"C:\Users\User\Desktop\exp.evtx"); } public static void BackupEventLogFilterBySource(String logName, String applicationName, String targetFile) { ManagementScope scope = new ManagementScope(@"\\.\root\cimv2"); scope.Options.EnablePrivileges = true; scope.Options.Impersonation = ImpersonationLevel.Impersonate; ObjectQuery query = new ObjectQuery( String.Format("Select * from Win32_NTEventLogFile Where LogFileName='{0}' And Sources='{1}'", logName, applicationName) ); using (ManagementObjectSearcher search = new ManagementObjectSearcher(scope, query)) { foreach (ManagementObject o in search.Get()) { ManagementBaseObject inParams = o.GetMethodParameters("BackupEventlog"); inParams["ArchiveFileName"] = targetFile; ManagementBaseObject outParams = o.InvokeMethod("BackupEventLog", inParams, null); var res = outParams.Properties["ReturnValue"].Value; Console.Write("result=" + res + "\n"); } } }
但该查询失败,出现以下exception:
System.Management.dll中发生了未处理的“System.Management.ManagementException”类型exception
其他信息:无效的查询
那么我在这里做错了什么?
用于标识Source
的内部名称可能与计算机管理UI中显示的内部名称不同。
例如,Source Winlogon
内部被引用为Microsoft-Windows-Winlogon
。
此外, Sources
参数存在问题,因为它是一个数组。
此修改方法使用Win32_NTLogEvent
而不是Win32_NTEventLogFile
。
我认为它更直接地针对目标。
由于我提到的原因,查询使用LIKE '%parameter%'
来过滤Source。 但是,可以使用LogFileName
filter使用原始方法提取所有源名称,并分析Sources { }
数组的内容。
从日志源文件中提取的值存储在列表中。
您可以使用它的属性创建一个类似于您在事件查看器中看到的报告。
注意:可以使用ManagementDateTimeConverter .ToDateTime方法将
TimeGenerated
和TimeLogged
属性转换为DateTime
public class WinLogEvent { public string ComputerName { get; set; } public string LogName { get; set; } public string Message { get; set; } public string Source { get; set; } public UInt16 EventCode { get; set; } public uint EventIdentifier { get; set; } public string EventType { get; set; } public uint RecordNumber { get; set; } public DateTime? TimeGenerated { get; set; } public DateTime? TimeLogged { get; set; } public byte[] Data { get; set; } public string[] InsertionStrings { get; set; } } public List BackupEventLogFilterBySource(string logName, string sourceName) { List LogEvents = new List (); ConnectionOptions _ConnOptions = new ConnectionOptions(); _ConnOptions.EnablePrivileges = true; _ConnOptions.Timeout = EnumerationOptions.InfiniteTimeout; _ConnOptions.Authentication = AuthenticationLevel.Default; _ConnOptions.Impersonation = ImpersonationLevel.Impersonate; //Add (if needed) => .UserName, .Password, .Authority ManagementScope _Scope = new ManagementScope(@"\\" + Environment.MachineName + @"\root\CIMV2", _ConnOptions); _Scope.Connect(); SelectQuery _Query = new SelectQuery("SELECT * FROM Win32_NTLogEvent"); _Query.Condition = string.Format("Logfile='{0}' AND SourceName LIKE '%{1}%'", logName, sourceName); EnumerationOptions _Options = new EnumerationOptions(); _Options.Rewindable = true; _Options.ReturnImmediately = true; using (ManagementObjectSearcher search = new ManagementObjectSearcher(_Scope, _Query, _Options)) { foreach (ManagementObject _EventLog in search.Get()) { LogEvents.Add(new WinLogEvent { ComputerName = _EventLog.GetPropertyValue("ComputerName").ToString(), LogName = _EventLog.GetPropertyValue("Logfile").ToString(), Source = _EventLog.GetPropertyValue("SourceName").ToString(), EventCode = (UInt16)_EventLog.GetPropertyValue("EventCode"), EventIdentifier = (uint)_EventLog.GetPropertyValue("EventIdentifier"), EventType = _EventLog.GetPropertyValue("Type").ToString(), RecordNumber = (uint)_EventLog.GetPropertyValue("RecordNumber"), TimeGenerated = ManagementDateTimeConverter.ToDateTime(_EventLog.GetPropertyValue("TimeGenerated").ToString()), TimeLogged = ManagementDateTimeConverter.ToDateTime(_EventLog.GetPropertyValue("TimeWritten").ToString()), Message = _EventLog.GetPropertyValue("Message") != null ? _EventLog.GetPropertyValue("Message").ToString() : string.Empty, InsertionStrings = (string[])_EventLog.GetPropertyValue("InsertionStrings"), Data = (byte[])_EventLog.GetPropertyValue("Data"), }); } } return LogEvents; }
在您的查询中,您必须将sources
替换为SourceName
。 为了获得正确的WMI查询,请使用wbemtest
,它会让您知道要查询的字段。