// 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);
}
}
}