// 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.IO; namespace Spludlow { public class Diagnostics { public static void DailyHost(int keepTempFileHistoryDays) { int keepLogHistoryDays = 28; DateTime deleteLogHistoryBefore = DateTime.Now.Date.AddDays(-keepLogHistoryDays); if (Spludlow.Config.Get("Spludlow.Host.Log") == Environment.MachineName) Spludlow.Log.Clear(deleteLogHistoryBefore); DateTime deleteTempFileBefore = DateTime.Now.Date.AddDays(-keepTempFileHistoryDays); Spludlow.WebServices.CleanProgramDataTempFiles(deleteTempFileBefore); Spludlow.Printing.PrinterHistory.Clear(deleteTempFileBefore); } public static DataSet SystemTimeCheck() { DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Pass Host SystemTime", "Int32 String DateTime", }); for (int pass = 1; pass <= 3; ++pass) { List tasks = new List(); foreach (string host in Spludlow.Config.Hosts()) tasks.Add(new Task(() => SystemTimeCheckWork(table, host, pass))); foreach (Task task in tasks) task.Start(); Task.WaitAll(tasks.ToArray()); System.Threading.Thread.Sleep(1000); } Spludlow.Log.Report("System Time Check", new object[] { table }); return Spludlow.Data.ADO.WireDataSet(table); } private static void SystemTimeCheckWork(DataTable table, string host, int pass) { DateTime remoteTime = (DateTime)Spludlow.Call.Now(host, "System", "System.DateTime", "Now"); lock (table) { table.Rows.Add(new object[] { pass, host, remoteTime }); } } public static void DeleteFilesWithReport(string directory, DateTime beforeDate) { if (Directory.Exists(directory) == false) return; DirectoryInfo tempDirInfo = new DirectoryInfo(directory); DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Filename Length LastWriteTime Error", "String Int64 DateTime String", }); long totalFileSize = 0; foreach (FileInfo fileInfo in tempDirInfo.GetFiles()) { if (fileInfo.LastWriteTime >= beforeDate) continue; DataRow row = table.Rows.Add(new object[] { fileInfo.FullName, fileInfo.Length, fileInfo.LastWriteTime, "" }); try { File.Delete(fileInfo.FullName); totalFileSize += fileInfo.Length; } catch (Exception ee) { row["Error"] = ee.Message; } } Spludlow.Log.Report("Delete Files With Report: " + directory + ", count: " + table.Rows.Count + ", total size: " + Spludlow.Text.DataSize(totalFileSize), new object[] { table }); } public static void StartStoppedAllHosts() { List tasks = new List(); foreach (string host in Spludlow.Config.Hosts()) { if (host == Environment.MachineName) StartStopped(); else tasks.Add(new Task(() => StartStopped(host))); } foreach (Task task in tasks) task.Start(); Task.WaitAll(tasks.ToArray()); } public static int StartStopped(string host) { try { return (int)Spludlow.Call.Now(host, "Spludlow", "Spludlow.Diagnostics", "StartStopped", CallFlags.NonPersistent); } catch (Exception ee) { Spludlow.Log.Error("Diagnostics, StartStopped; Web Service Call", ee); return 1; } } public static int StartStopped() { int total = 0; total += StartStoppedTheads(); total += StartStoppedWebs(); total += StartStoppedServices(); return total; } public static int StartStoppedTheads() { Spludlow.SysTables.StatusDataTable table = QueryLocal(); if (table == null) { Spludlow.Log.Error("Diagnostics, StartStoppedTheads; Can't get status"); return 1; } List serviceThreads = new List(); foreach (Spludlow.SysTables.StatusRow row in table.Rows) { if (row.IsTaskTypeNull() == true || row.IsHostedNull() == true || row.IsServiceStateNull() == true) { continue; } if (row.TaskType != "Method") continue; if (row.ServiceState != "Running") { Spludlow.Log.Warning("Diagnostics, StartStoppedTheads; Service not running: " + row.Hosted); continue; } if (row.IsThreadStateNull() == true) { Spludlow.Log.Warning("Diagnostics, StartStoppedTheads; ThreadState is Null: " + row.Hosted + ", " + row.Thread); continue; } if (row.ThreadState != "Aborted" && row.ThreadState != "Stopped") continue; serviceThreads.Add(new string[] { row.ApplicationId, row.Thread }); } foreach (string[] words in serviceThreads) { string service = words[0]; string thread = words[1]; try { Spludlow.Service.StartThreadWork(service, thread); Spludlow.Log.Report("Diagnostics, StartStoppedTheads; Started Thread: " + service + ", " + thread); } catch (Exception ee) { Spludlow.Log.Error("Diagnostics, StartStoppedTheads; Starting Thread: " + service + ", " + thread, ee); } } return serviceThreads.Count; } public static int StartStoppedWebs() { Spludlow.SysTables.StatusDataTable table = QueryLocal(); if (table == null) { Spludlow.Log.Error("Diagnostics, StartStoppedWebs; Can't get status"); return 1; } List applicationPools = new List(); foreach (Spludlow.SysTables.StatusRow row in table.Rows) { if (row.IsTaskTypeNull() == true || row.IsHostedNull() == true || row.IsServiceStateNull() == true || row.IsThreadStateNull() == true) { continue; } if (row.TaskType != "Web") continue; if (row.ServiceState != "Running") { Spludlow.Log.Warning("Diagnostics, StartStoppedWebs; IIS not running: " + row.Hosted); continue; } if (row.ThreadState != "Stopped") continue; if (applicationPools.Contains(row.Hosted) == false) applicationPools.Add(row.Hosted); } foreach (string applicationPool in applicationPools) { try { Spludlow.Admin.WebStart(applicationPool); Spludlow.Log.Report("Diagnostics, StartStoppedWebs; Started Application Pool: " + applicationPool); } catch (Exception ee) { Spludlow.Log.Error("Diagnostics, StartStoppedWebs; Starting Application Pool: " + applicationPool, ee); } } return applicationPools.Count; } public static int StartStoppedServices() { Spludlow.SysTables.StatusDataTable table = QueryLocal(); if (table == null) { Spludlow.Log.Error("Diagnostics, StartStoppedServices; Can't get status"); return 1; } bool iisStopped = false; List serviceProcesses = new List(); foreach (Spludlow.SysTables.StatusRow row in table.Rows) { if (row.IsTaskTypeNull() == true || row.IsHostedNull() == true || row.IsServiceStateNull() == true) { continue; } if (row.TaskType == "Web" && row.ServiceState == "Stopped") { iisStopped = true; continue; } if (row.TaskType != "Method" && row.TaskType != "Server") continue; if (row.ServiceState != "Stopped") continue; if (serviceProcesses.Contains(row.Hosted) == false) serviceProcesses.Add(row.Hosted); } if (iisStopped == true) serviceProcesses.Add("W3SVC"); foreach (string serviceProcess in serviceProcesses) { try { Spludlow.Admin.ServiceStart(serviceProcess); Spludlow.Log.Report("Diagnostics, StartStoppedServices; Started Service: " + serviceProcess); } catch (Exception ee) { Spludlow.Log.Error("Diagnostics, StartStoppedServices; Starting Service: " + serviceProcess, ee); } } return serviceProcesses.Count; } private static Spludlow.SysTables.StatusDataTable QueryLocal() { try { DataSet dataSet = Spludlow.Status.QueryLocal(); return (Spludlow.SysTables.StatusDataTable)dataSet.Tables[0]; } catch (Exception ee) { Spludlow.Log.Error("Diagnostics, QueryLocal", ee); return null; } } /// /// Used to make checks on boot /// look for new crash dump /// public static void HostBootCheck() { string address = Environment.MachineName + ":Sys"; Spludlow.Call.Queue(address, "Spludlow", "Spludlow.Diagnostics", "HostBootCheckWork"); } public static void HostBootCheckWork() { string variableName = "Spludlow.Diagnostics.LastHostCrash"; string filename = @"C:\Windows\MEMORY.DMP"; if (File.Exists(filename) == false) return; string currentCrash = File.GetLastWriteTime(filename).ToString(); string lastCrash = Spludlow.Variables.GetValue(variableName); if (lastCrash != null && lastCrash == currentCrash) return; string info = Environment.MachineName + ", " + currentCrash; Spludlow.Log.Error("Blue Screen of Death, " + info); Spludlow.Email.SendMail.Send("Blue Screen of Death, " + info, info); Spludlow.Variables.SetValue(variableName, currentCrash); } } }