Mercurial > servermonitor
diff ServerMonitor/Objects/ServerMonitor.cs @ 8:052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Sat, 09 Mar 2019 20:14:03 -0500 |
parents | c1dffaac66fa |
children | 68d7834dc28e |
line wrap: on
line diff
--- a/ServerMonitor/Objects/ServerMonitor.cs Fri Mar 01 21:39:22 2019 -0500 +++ b/ServerMonitor/Objects/ServerMonitor.cs Sat Mar 09 20:14:03 2019 -0500 @@ -1,4 +1,5 @@ -using Renci.SshNet; +using Microsoft.Win32; +using Renci.SshNet; using Renci.SshNet.Common; using ServerMonitorApp.Properties; using System; @@ -22,7 +23,7 @@ private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>(); private readonly Dictionary<string, PrivateKeyFile> privateKeys = new Dictionary<string, PrivateKeyFile>(); private readonly List<int> pausedChecks = new List<int>(); - private bool running, networkAvailable; + private bool running, networkAvailable, suspend; private Dictionary<Task<CheckResult>, int> tasks; private ServerSummaryForm mainForm; @@ -60,6 +61,7 @@ public void LoadServers() { + Read: TextReader reader = null; try { @@ -89,14 +91,18 @@ catch (DirectoryNotFoundException) { } catch (InvalidOperationException) { - //TODO log - throw; + reader?.Close(); + File.Copy(ConfigFile, ConfigFile + ".error", true); + File.Copy(ConfigFile + ".bak", ConfigFile, true); + goto Read; } finally { reader?.Close(); } + Application.ApplicationExit += Application_ApplicationExit; NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; + SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; logger.TrimLog(); Run(); } @@ -108,6 +114,11 @@ XmlSerializer serializer = null; try { + File.Copy(ConfigFile, ConfigFile + ".bak", true); + } + catch { } + try + { writer = new StreamWriter(ConfigFile); serializer = CreateXmlSerializer(); serializer.Serialize(writer, Servers); @@ -119,11 +130,6 @@ serializer = CreateXmlSerializer(); serializer.Serialize(writer, Servers); } - catch (Exception) - { - //TODO log - throw; - } finally { writer?.Close(); @@ -132,7 +138,7 @@ private async void Run() { - if (running) + if (running || suspend) return; running = true; networkAvailable = Helpers.IsNetworkAvailable(); @@ -144,8 +150,6 @@ } pausedChecks.Clear(); } - //TODO subscribe to power events. Find any check's NextExecutionTime is in the past. Cancel waiting task and run immediately (or after short delay). - //tasks = Checks.Select(c => ScheduleExecuteCheckAsync(c)).ToList(); tasks = Checks.ToDictionary(c => ScheduleExecuteCheckAsync(c), c => c.Id); while (tasks.Count > 0) { @@ -171,6 +175,8 @@ check.Status = CheckStatus.Running; OnCheckStatusChanged(check); CheckResult result = await check.ExecuteAsync(token); + if (result.Failed) + check.ConsecutiveFailures++; OnCheckStatusChanged(check, result); HandleResultAsync(result); return result; @@ -179,10 +185,13 @@ private void HandleResultAsync(CheckResult result) { logger.Log(result); - if (result.FailAction == FailAction.FlashTaskbar) - mainForm.AlertServerForm(result.Check); - if (result.FailAction.In(FailAction.FlashTaskbar, FailAction.NotificationBalloon)) - mainForm.ShowBalloon(result); + if (result.Check.ConsecutiveFailures >= result.Check.MaxConsecutiveFailures) + { + if (result.FailAction == FailAction.FlashTaskbar) + mainForm.AlertServerForm(result.Check); + if (result.FailAction.In(FailAction.FlashTaskbar, FailAction.NotificationBalloon)) + mainForm.ShowBalloon(result); + } } public IList<CheckResult> GetLog(Server server) @@ -261,10 +270,13 @@ CancellationTokenSource cts = new CancellationTokenSource(); tokens[check.Id] = cts; check.NextRunTime = check.Schedule.GetNextTime(check.LastScheduledRunTime); - await Task.Delay(check.NextRunTime - DateTime.Now, cts.Token); + int delay = Math.Max(0, (int)(check.NextRunTime - DateTime.Now).TotalMilliseconds); + await Task.Delay(delay, cts.Token); check.LastScheduledRunTime = check.NextRunTime; - if (networkAvailable) + if (networkAvailable && !cts.IsCancellationRequested) + { return await ExecuteCheckAsync(check, cts.Token); + } else { if (!pausedChecks.Contains(check.Id)) @@ -280,25 +292,61 @@ mainForm.Invoke((MethodInvoker)(() => Run())); } + private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + { + if (e.Mode == PowerModes.Suspend) + { + foreach (Check check in Checks) + { + CancelCheck(check); + } + suspend = true; + } + else if (e.Mode == PowerModes.Resume) + { + pausedChecks.Clear(); + foreach (Check check in Checks) + { + //CancelCheck(check); + if (check.Enabled && check.Server.Enabled && check.NextRunTime < DateTime.Now) + { + pausedChecks.Add(check.Id); + } + } + await Task.Delay(10000); + suspend = false; + Run(); + } + } + + private void Application_ApplicationExit(object sender, EventArgs e) + { + NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged; + SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; + } + public KeyStatus OpenPrivateKey(string path, string password = null) { KeyStatus keyStatus; if (path == null) - return KeyStatus.NotAccessible; + keyStatus = KeyStatus.NotAccessible; if (privateKeys.TryGetValue(path, out PrivateKeyFile key) && key != null) - return KeyStatus.Open; - try - { - key = new PrivateKeyFile(path, password); keyStatus = KeyStatus.Open; - } - catch (Exception e) when (e is SshPassPhraseNullOrEmptyException || e is InvalidOperationException) + else { - keyStatus = KeyStatus.NeedPassword; - } - catch (Exception) - { - keyStatus = KeyStatus.NotAccessible; + try + { + key = new PrivateKeyFile(path, password); + keyStatus = KeyStatus.Open; + } + catch (Exception e) when (e is SshPassPhraseNullOrEmptyException || e is InvalidOperationException) + { + keyStatus = KeyStatus.NeedPassword; + } + catch (Exception) + { + keyStatus = KeyStatus.NotAccessible; + } } foreach (Server server in Servers) {