// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Diagnostics; namespace Spludlow { /// /// Query Windows Event Logs /// /// Put this together to find ESENT warnings that can indicate disk failure before getting actual disk errors /// /// Normally the Admin Web Service will query the event logs /// extraHosts are used to query a remote host that is not running the Spludlow framework. DOM & WMI Permissions must be enabled for SpludlowGroup /// public class EventLogs { public static void ReportProblems(int days, string[] extraHosts, bool mailResult) { DataSet dataSet = QueryAllHosts(days, extraHosts); ReportProblems(dataSet, mailResult); } public static void ReportProblems(DataSet hostsEventLogs, bool mailResult) { DataTable resultTable = null; foreach (DataTable table in hostsEventLogs.Tables) { if (resultTable == null) { resultTable = new DataTable(); resultTable.Columns.Add("Host", typeof(string)); resultTable.Columns.Add("LogName", typeof(string)); foreach (DataColumn column in table.Columns) resultTable.Columns.Add(column.ColumnName, column.DataType); } int index = table.TableName.LastIndexOf("_"); string host = table.TableName.Substring(0, index); string logName = table.TableName.Substring(index + 1); foreach (DataRow sourceRow in table.Rows) { DataRow useRow = null; switch (logName) { case "Application": useRow = sourceRow; break; case "Security": break; case "System": useRow = sourceRow; break; }; if (useRow != null) { resultTable.ImportRow(useRow); DataRow row = resultTable.Rows[resultTable.Rows.Count - 1]; row["Host"] = host; row["LogName"] = logName; } } } string subject = "EventLogs ReportProblems " + Spludlow.Text.TimeStamp(); Spludlow.Log.Report(subject, resultTable); if (mailResult == true && resultTable != null) Spludlow.Email.SendMail.Send(subject, resultTable); } public static DataSet QueryAllHosts(int days, string[] extraHosts) { List hostList = new List(Spludlow.Config.Hosts()); if (extraHosts != null) foreach (string otherHost in extraHosts) hostList.Add("@" + otherHost); string[] hosts = hostList.ToArray(); DataSet dataSet = new DataSet(); Task[] tasks = new Task[hosts.Length]; for (int index = 0; index < hosts.Length; ++index) { string host = hosts[index]; tasks[index] = new Task(() => QueryAllHostsWorker(dataSet, host, days)); } foreach (Task task in tasks) task.Start(); Task.WaitAll(tasks); return dataSet; } private static void QueryAllHostsWorker(DataSet dataSet, string host, int days) { DataSet hostDataSet; if (host.StartsWith("@") == true) { host = host.Substring(1); hostDataSet = Spludlow.EventLogs.QueryRaw(host, days, false); } else { hostDataSet = Spludlow.EventLogs.Query(host, 14, false); } List tableList = new List(); foreach (DataTable table in hostDataSet.Tables) tableList.Add(table); foreach (DataTable table in tableList) { table.TableName = host + "_" + table.TableName; hostDataSet.Tables.Remove(table); lock (dataSet) { dataSet.Tables.Add(table); } } } public static DataSet Query(string host, int daysBack, bool includeEverything) { return Spludlow.Admin.QueryEventLogs(host, daysBack, includeEverything); } public static DataSet QueryRaw(int daysBack, bool includeEverything) { return QueryRaw(null, daysBack, includeEverything); } public static DataSet QueryRaw(string remoteHost, int daysBack, bool includeEverything) { DateTime startDate = DateTime.Now.Date.AddDays(-daysBack); DataSet dataSet = new DataSet(); string[] logNames = new string[] { "Application", "Security", "System" }; foreach (string logName in logNames) { DataTable table = Spludlow.Data.TextTable.ReadText(logName, new string[] { "EntryType", "String", }); Spludlow.Data.ADO.ReflectNewTable(table, typeof(EventLogEntry)); using (EventLog eventLog = GetEventLog(logName, remoteHost)) { foreach (EventLogEntry entry in eventLog.Entries) { if (entry.TimeGenerated < startDate) continue; if (includeEverything == false) { if (entry.EntryType != EventLogEntryType.Error && entry.EntryType != EventLogEntryType.Warning && entry.EntryType != EventLogEntryType.FailureAudit) continue; if (entry.InstanceId == 10016 && entry.Source == "DCOM") // https://support.microsoft.com/en-gb/help/4022522/dcom-event-id-10016-is-logged-in-windows-10-and-windows-server-2016 continue; } DataRow row = Spludlow.Data.ADO.ReflectNewRow(table, entry); row["EntryType"] = entry.EntryType.ToString(); } } table.Columns.Remove("ReplacementStrings"); // would like to be able to use texttables Spludlow.Data.TextTable.CleanWhiteSpace(table); dataSet.Tables.Add(table); } return dataSet; } public static void ClearRaw(string remoteHost, string logName) { using (EventLog eventLog = GetEventLog(logName, remoteHost)) { eventLog.Clear(); } } private static EventLog GetEventLog(string logName, string host) { if (host == null) return new EventLog(logName); else return new EventLog(logName, host); } } }