I'm trying to use Win32_NTEventLogFile
WMI class to export the Applications
branch of the Windows Event log, but filter it only for a specific source. (Otherwise the log contains too much unnecessary information.)
So, just as an example, say, I need to export all records that contain MSSQL$SQLSRVR2012
:
I do this:
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");
}
}
}
But that query fails with the following exception:
An unhandled exception of type 'System.Management.ManagementException' occurred in System.Management.dll
Additional information: Invalid query
So what am I doing wrong here?
The internal name used to identify the Source
may be different from what is presented in the Computer Management UI.
For example, the Source Winlogon
, internally is referenced as Microsoft-Windows-Winlogon
.
Also, there's a problem with the Sources
parameter, since it's an array.
This modified method uses Win32_NTLogEvent
instead of Win32_NTEventLogFile
.
I think it goes more directly to the target.
The query uses LIKE '%parameter%'
to filter the Source, for the reason I mentioned. It's however possible to extract all the sources names using your original method with the LogFileName
filter and analyse the content of the Sources { }
array.
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