我正在尝试使用 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");
}
}
}
但是该查询失败并出现以下异常:
An unhandled exception of type 'System.Management.ManagementException' occurred in System.Management.dll
Additional information: Invalid query
那么我做错了什么?
最佳答案
用于标识源
的内部名称可能与计算机管理 UI 中显示的名称不同。
例如,源代码 Winlogon
,在内部被引用为 Microsoft-Windows-Winlogon
。
此外,Sources
参数也有问题,因为它是一个数组。
此修改后的方法使用 Win32_NTLogEvent
而不是 Win32_NTEventLogFile
。
我认为它更直接地达到了目标。
由于我提到的原因,查询使用 LIKE '%parameter%'
来过滤源。但是,可以使用带有 LogFileName
过滤器的原始方法提取所有源名称,并分析 Sources { }
数组的内容。
从日志源文件中提取的值存储在列表中。
您可以使用它的属性来创建类似于您在事件查看器中看到的报告。
Note: The
TimeGenerated
andTimeLogged
properties can be converted toDateTime
using the ManagementDateTimeConverter .ToDateTime Method
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; }
}
private static EnumerationOptions GetEnumerationOptions(bool deepScan)
{
var mOptions = new EnumerationOptions()
{
Rewindable = false, //Forward only query => no caching
ReturnImmediately = true, //Pseudo-async result
DirectRead = true,
EnumerateDeep = deepScan
};
return mOptions;
}
private static ConnectionOptions GetConnectionOptions(string UserName, string Password, string Domain)
{
var connOptions = new ConnectionOptions()
{
EnablePrivileges = true,
Timeout = ManagementOptions.InfiniteTimeout,
Authentication = AuthenticationLevel.PacketPrivacy,
Impersonation = ImpersonationLevel.Default,
Username = UserName,
Password = Password,
//Authority = "NTLMDOMAIN:[domain]"
Authority = !string.IsNullOrEmpty(Domain) ? $"NTLMDOMAIN:{Domain}" : string.Empty
};
return connOptions;
}
public static List<WinLogEvent> BackupEventLogFilterBySource(string logName, string sourceName)
{
List<WinLogEvent> logEvents = new List<WinLogEvent>();
var connOptions = GetConnectionOptions(null, null, null);
var options = GetEnumerationOptions(false);
var scope = new ManagementScope(@"\\" + Environment.MachineName + @"\root\CIMV2", connOptions);
scope.Connect();
var query = new SelectQuery("SELECT * FROM Win32_NTLogEvent");
query.Condition = $"Logfile='{logName}' AND SourceName LIKE '%{sourceName}%'";
using (ManagementObjectSearcher moSearch = new ManagementObjectSearcher(scope, query, options))
{
foreach (ManagementObject eventLog in moSearch.Get())
{
ManagementBaseObject inParams = eventLog.GetMethodParameters("BackupEventlog");
inParams["ArchiveFileName"] = @"D:\exp.evtx";
ManagementBaseObject outParams = eventLog.InvokeMethod("BackupEventLog", inParams, null);
var res = outParams.Properties["ReturnValue"].Value;
logEvents.Add(new WinLogEvent
{
ComputerName = eventLog.GetPropertyValue("ComputerName")?.ToString(),
LogName = eventLog.GetPropertyValue("Logfile")?.ToString(),
Source = eventLog.GetPropertyValue("SourceName")?.ToString(),
EventCode = (UInt16?)eventLog.GetPropertyValue("EventCode") ?? 0,
EventIdentifier = (uint?)eventLog.GetPropertyValue("EventIdentifier") ?? 0,
EventType = eventLog.GetPropertyValue("Type")?.ToString(),
RecordNumber = (uint?)eventLog.GetPropertyValue("RecordNumber") ?? 0,
TimeGenerated = ManagementDateTimeConverter.ToDateTime(eventLog.GetPropertyValue("TimeGenerated")?.ToString()),
TimeLogged = ManagementDateTimeConverter.ToDateTime(eventLog.GetPropertyValue("TimeWritten")?.ToString()),
Message = eventLog.GetPropertyValue("Message")?.ToString(),
InsertionStrings = (string[])eventLog.GetPropertyValue("InsertionStrings") ?? null,
Data = (byte[])eventLog.GetPropertyValue("Data") ?? null,
});
inParams.Dispose();
outParams.Dispose();
}
}
return logEvents;
} //BackupEventLogFilterBySource
关于c# - 如何使用 WMI 导出特定来源的 Windows 事件日志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48972882/