如何使用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。 但是,可以使用LogFileNamefilter使用原始方法提取所有源名称,并分析Sources { }数组的内容。


从日志源文件中提取的值存储在列表中。
您可以使用它的属性创建一个类似于您在事件查看器中看到的报告。

注意:可以使用ManagementDateTimeConverter .ToDateTime方法将TimeGeneratedTimeLogged属性转换为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 ,它会让您知道要查询的字段。