Mercurial > servermonitor
annotate ServerMonitor/Objects/ServerMonitor.cs @ 19:b3128fe10d57
Add About form and license.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Wed, 29 May 2019 20:18:37 -0400 |
parents | 68d7834dc28e |
children | 781d8b980be1 |
rev | line source |
---|---|
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
1 using Microsoft.Win32; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
2 using Renci.SshNet; |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
3 using Renci.SshNet.Common; |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
4 using ServerMonitorApp.Properties; |
4 | 5 using System; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
6 using System.Collections.Generic; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
7 using System.IO; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
8 using System.Linq; |
4 | 9 using System.Net.NetworkInformation; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
10 using System.Threading; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
11 using System.Threading.Tasks; |
4 | 12 using System.Windows.Forms; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
13 using System.Xml.Serialization; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
14 |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
15 namespace ServerMonitorApp |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
16 { |
17 | 17 /// <summary>Central class for scheduling and executing checks against remote servers.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
18 public class ServerMonitor |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
19 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
20 private readonly string configFileDir; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
21 private readonly Logger logger; |
17 | 22 // Cancellation tokens for executing checks, keyed by check ID. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
23 private readonly Dictionary<int, CancellationTokenSource> tokens = new Dictionary<int, CancellationTokenSource>(); |
17 | 24 // SSH private keys, keyed by the path to the private key file. |
25 // A value of NULL indicates that the private key is inaccessible or encrypted. | |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
26 private readonly Dictionary<string, PrivateKeyFile> privateKeys = new Dictionary<string, PrivateKeyFile>(); |
17 | 27 // IDs of all checks that have been paused due to network unavailability, |
28 // or due to the system being suspended. | |
29 // Not to be confused with checks that have been disabled by the user. | |
4 | 30 private readonly List<int> pausedChecks = new List<int>(); |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
31 private bool running, networkAvailable, suspend; |
17 | 32 // List of check execution tasks that have been started. |
33 // A check task begins by sleeping until the next scheduled execution time, | |
34 // then executes. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
35 private Dictionary<Task<CheckResult>, int> tasks; |
4 | 36 private ServerSummaryForm mainForm; |
37 | |
17 | 38 /// <summary>Fires when the status of a check changes.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
39 public event EventHandler<CheckStatusChangedEventArgs> CheckStatusChanged; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
40 |
17 | 41 /// <summary>The collection of registered servers.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
42 public List<Server> Servers { get; private set; } = new List<Server>(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
43 |
17 | 44 /// <summary>A collection of all checks belonging to all registerd servers.</summary> |
4 | 45 public IEnumerable<Check> Checks => Servers.SelectMany(s => s.Checks); |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
46 |
17 | 47 /// <summary>Path to the file that stores server and check configuration.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
48 public string ConfigFile { get; private set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
49 |
17 | 50 /// <summary>Path to the file that stores server and check configuration.</summary> |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
51 public IEnumerable<string> LockedKeys { get { return privateKeys.Where(kvp => kvp.Value == null).Select(kvp => kvp.Key); } } |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
52 |
17 | 53 /// <summary>ServerMonitor constructor.</summary> |
54 /// <param name="mainForm">A reference to the main form.</param> | |
4 | 55 public ServerMonitor(ServerSummaryForm mainForm) |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
56 { |
4 | 57 this.mainForm = mainForm; |
17 | 58 // Store configuration in %appdata%\ServerMonitor |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
59 configFileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ServerMonitor"); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
60 ConfigFile = Path.Combine(configFileDir, "servers.xml"); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
61 logger = new Logger(Path.Combine(configFileDir, "monitor.log")); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
62 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
63 |
17 | 64 /// <summary>Registers a new server with the server monitor.</summary> |
65 /// <param name="server">The server to be added.</param> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
66 public void AddServer(Server server) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
67 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
68 Servers.Add(server); |
4 | 69 SaveServers(); |
70 } | |
71 | |
17 | 72 /// <summary>Deletes a server from the server monitor.</summary> |
73 /// <param name="server">The server to be deleted.</param> | |
4 | 74 public void DeleteServer(Server server) |
75 { | |
76 Servers.Remove(server); | |
77 SaveServers(); | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
78 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
79 |
17 | 80 /// <summary>Loads all servers and checks from the config file.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
81 public void LoadServers() |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
82 { |
17 | 83 bool triedBackup = false; |
84 | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
85 Read: |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
86 TextReader reader = null; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
87 try |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
88 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
89 reader = new StreamReader(ConfigFile); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
90 XmlSerializer serializer = CreateXmlSerializer(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
91 Servers.Clear(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
92 Servers.AddRange((List<Server>)serializer.Deserialize(reader)); |
17 | 93 // Do some more set-up now that the servers and checks have been loaded. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
94 foreach (Server server in Servers) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
95 { |
17 | 96 // Read private keys into memory if they are accessible and not encrypted. |
97 // If PrivateKeyFile != null, it means same the key has already been loaded for | |
98 // a different server and nothing more needs to be done. | |
6
c1dffaac66fa
- Don't show multiple password dialogs for the same key if the first one was cancelled.
Brad Greco <brad@bgreco.net>
parents:
5
diff
changeset
|
99 if (server.LoginType == LoginType.PrivateKey && server.PrivateKeyFile == null) |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
100 OpenPrivateKey(server.KeyFile); |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
101 foreach (Check check in server.Checks) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
102 { |
17 | 103 // Update the checks so they know what server they belong to. |
104 // Would rather do this in the Server object on deserialization, but | |
105 // that doesn't work when using the XML serializer for some reason. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
106 check.Server = server; |
17 | 107 // If the program last exited while the check was running, change its status |
108 // to the result of its last execution (since, at this point, the check is | |
109 // not running). | |
4 | 110 if (check.Status == CheckStatus.Running) |
111 check.Status = check.LastRunStatus; | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
112 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
113 server.CheckModified += Server_CheckModified; |
4 | 114 server.EnabledChanged += Server_EnabledChanged; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
115 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
116 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
117 // If the file doesn't exist, no special handling is needed. It will be created later. |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
118 catch (FileNotFoundException) { } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
119 catch (DirectoryNotFoundException) { } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
120 catch (InvalidOperationException) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
121 { |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
122 reader?.Close(); |
17 | 123 // If there was an error parsing the XML, try again with the backup config file. |
124 if (!triedBackup) | |
125 { | |
126 File.Copy(ConfigFile, ConfigFile + ".error", true); | |
127 string backupConfig = ConfigFile + ".bak"; | |
128 if (File.Exists(backupConfig)) | |
129 { | |
130 File.Copy(backupConfig, ConfigFile, true); | |
131 } | |
132 triedBackup = true; | |
133 goto Read; | |
134 } | |
135 else | |
136 { | |
137 // If there was an error reading the backup file too, give up. | |
138 throw; | |
139 } | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
140 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
141 finally |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
142 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
143 reader?.Close(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
144 } |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
145 Application.ApplicationExit += Application_ApplicationExit; |
4 | 146 NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
147 SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; |
17 | 148 |
149 // Remove old entries from the log file according to user preferences. | |
6
c1dffaac66fa
- Don't show multiple password dialogs for the same key if the first one was cancelled.
Brad Greco <brad@bgreco.net>
parents:
5
diff
changeset
|
150 logger.TrimLog(); |
17 | 151 |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
152 Run(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
153 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
154 |
17 | 155 /// <summary>Saves all servers and checks to the config file.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
156 public void SaveServers() |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
157 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
158 GenerateIds(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
159 TextWriter writer = null; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
160 XmlSerializer serializer = null; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
161 try |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
162 { |
17 | 163 // Make a backup first in case something goes wrong in the middle of writing. |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
164 File.Copy(ConfigFile, ConfigFile + ".bak", true); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
165 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
166 catch { } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
167 try |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
168 { |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
169 writer = new StreamWriter(ConfigFile); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
170 serializer = CreateXmlSerializer(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
171 serializer.Serialize(writer, Servers); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
172 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
173 catch (DirectoryNotFoundException) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
174 { |
17 | 175 // If the directory does not exist, create it and try again. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
176 Directory.CreateDirectory(configFileDir); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
177 writer = new StreamWriter(ConfigFile); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
178 serializer = CreateXmlSerializer(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
179 serializer.Serialize(writer, Servers); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
180 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
181 finally |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
182 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
183 writer?.Close(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
184 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
185 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
186 |
17 | 187 /// <summary>Main server monitor loop. Schedules and executes checks.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
188 private async void Run() |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
189 { |
17 | 190 // Do not run again if already running or if the system is suspending or resuming. |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
191 if (running || suspend) |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
192 return; |
17 | 193 |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
194 running = true; |
17 | 195 |
196 // If the network is available, immediately execute checks that were supposed to run | |
197 // earlier but could not due to network unavailability or the system being suspended. | |
4 | 198 networkAvailable = Helpers.IsNetworkAvailable(); |
199 if (networkAvailable) | |
200 { | |
201 foreach (int id in pausedChecks) | |
202 { | |
203 await ExecuteCheckAsync(Checks.FirstOrDefault(c => c.Id == id)); | |
204 } | |
205 pausedChecks.Clear(); | |
206 } | |
17 | 207 |
208 // Schedule all checks to run according to their schedules. | |
209 // Each check will sleep until it is scheduled to run, then execute. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
210 tasks = Checks.ToDictionary(c => ScheduleExecuteCheckAsync(c), c => c.Id); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
211 while (tasks.Count > 0) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
212 { |
17 | 213 // When any check is done sleeping and executing, remove the completed |
214 // task and queue a new task to schedule it again. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
215 Task<CheckResult> task = await Task.WhenAny(tasks.Keys); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
216 tasks.Remove(task); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
217 try |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
218 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
219 CheckResult result = await task; |
17 | 220 // Do not schedule the task again if it is now disabled. |
221 // Result will be null if a scheduled check was disabled. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
222 if (result != null && result.CheckStatus != CheckStatus.Disabled) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
223 tasks.Add(ScheduleExecuteCheckAsync(result.Check), result.Check.Id); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
224 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
225 catch (OperationCanceledException) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
226 { |
17 | 227 // When a server's state changes to Disabled, any checks that are executing |
228 // are immediately cancelled. Silently catch these expected exceptions. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
229 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
230 } |
17 | 231 // If there are no enabled checks scheduled, exit the main loop. |
232 // It will be restarted when a check or server is enabled. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
233 running = false; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
234 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
235 |
17 | 236 /// <summary>Schedules a check to be run on its schedule.</summary> |
237 /// <param name="check">The check to execute.</param> | |
238 /// <returns>The async check result.</returns> | |
239 private async Task<CheckResult> ScheduleExecuteCheckAsync(Check check) | |
240 { | |
241 // Do not schedule or execute the check if it or its server is disabled. | |
242 if (!check.Enabled || !check.Server.Enabled) | |
243 return await Task.FromResult(new CheckResult(check, CheckStatus.Disabled, null)); | |
244 | |
245 // Create a cancellation token that will be used to cancel the check if it or | |
246 // its server is disabled while it is executing. | |
247 CancellationTokenSource cts = new CancellationTokenSource(); | |
248 tokens[check.Id] = cts; | |
249 | |
250 // Sleep until next time the check is supposed to be executed. | |
251 // Use the LastScheduledRunTime so manual executions by the user do not | |
252 // interfere with the schedule. | |
253 check.NextRunTime = check.Schedule.GetNextTime(check.LastScheduledRunTime); | |
254 int delay = Math.Max(0, (int)(check.NextRunTime - DateTime.Now).TotalMilliseconds); | |
255 await Task.Delay(delay, cts.Token); | |
256 check.LastScheduledRunTime = check.NextRunTime; | |
257 | |
258 // Execute the check if not cancelled. | |
259 if (!cts.IsCancellationRequested) | |
260 { | |
261 // If the network is available, execute the check. | |
262 // Otherwise, add it to the list of paused checks to be executed | |
263 // when the network becomes available again. | |
264 if (networkAvailable) | |
265 { | |
266 return await ExecuteCheckAsync(check, cts.Token); | |
267 } | |
268 else | |
269 { | |
270 if (!pausedChecks.Contains(check.Id)) | |
271 pausedChecks.Add(check.Id); | |
272 } | |
273 } | |
274 return await Task.FromResult(new CheckResult(check, CheckStatus.Disabled, null)); | |
275 } | |
276 | |
277 /// <summary>Executes a check asynchronously.</summary> | |
278 /// <param name="check">The check to execute.</param> | |
279 /// <param name="token">A chancellation token that may be used to cancel the check execution.</param> | |
280 /// <returns>The async check result.</returns> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
281 public async Task<CheckResult> ExecuteCheckAsync(Check check, CancellationToken token = default(CancellationToken)) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
282 { |
17 | 283 // Update the status. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
284 check.Status = CheckStatus.Running; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
285 OnCheckStatusChanged(check); |
17 | 286 |
287 // Execute the check. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
288 CheckResult result = await check.ExecuteAsync(token); |
17 | 289 |
290 // Increment the consecutive failure counter on failue, or reset | |
291 // the counter on success. | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
292 if (result.Failed) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
293 check.ConsecutiveFailures++; |
17 | 294 else |
295 check.ConsecutiveFailures = 0; | |
296 | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
297 OnCheckStatusChanged(check, result); |
4 | 298 HandleResultAsync(result); |
299 return result; | |
300 } | |
301 | |
17 | 302 /// <summary>Handles the result of a check execution.</summary> |
303 /// <param name="result">The result.</param> | |
4 | 304 private void HandleResultAsync(CheckResult result) |
305 { | |
17 | 306 // Log the result. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
307 logger.Log(result); |
17 | 308 |
309 // Notify the user of failure according to user preferences. | |
310 // If the check succeeded, result.FailAction will be None. | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
311 if (result.Check.ConsecutiveFailures >= result.Check.MaxConsecutiveFailures) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
312 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
313 if (result.FailAction == FailAction.FlashTaskbar) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
314 mainForm.AlertServerForm(result.Check); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
315 if (result.FailAction.In(FailAction.FlashTaskbar, FailAction.NotificationBalloon)) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
316 mainForm.ShowBalloon(result); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
317 } |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
318 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
319 |
17 | 320 /// <summary>Reads all check results from the log for a server.</summary> |
321 /// <param name="server">The server whose check results should be read.</param> | |
322 /// <returns>A list of all check results found in the log file for the given server.</returns> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
323 public IList<CheckResult> GetLog(Server server) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
324 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
325 return logger.Read(server); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
326 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
327 |
17 | 328 /// <summary>Saves the check settings and notifies event subscribers when the status of a check changes.</summary> |
329 /// <param name="check">The check whose status has changed.</param> | |
330 /// <param name="result">The check result that caused the status to change, if any.</param> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
331 private void OnCheckStatusChanged(Check check, CheckResult result = null) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
332 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
333 SaveServers(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
334 CheckStatusChanged?.Invoke(check, new CheckStatusChangedEventArgs(check, result)); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
335 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
336 |
17 | 337 /// <summary>Handles user modifications to a check's settings.</summary> |
338 /// <param name="sender">The check that was modified.</param> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
339 private void Server_CheckModified(object sender, EventArgs e) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
340 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
341 Check check = (Check)sender; |
17 | 342 |
343 // No need to mess with the task queue if not currently running. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
344 if (running) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
345 { |
17 | 346 Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
347 if (task == null) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
348 { |
17 | 349 // No tasks associated with the check, so schedule a new one. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
350 tasks.Add(ScheduleExecuteCheckAsync(check), check.Id); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
351 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
352 else |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
353 { |
17 | 354 // Check was modified or deleted, so remove any waiting tasks. |
4 | 355 CancelCheck(check); |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
356 if (check.Server != null) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
357 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
358 // If the check was not deleted, schedule the new check. |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
359 // But only if it's still running, otherwise restarting the monitor below |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
360 // will create a duplicate run. |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
361 if (running) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
362 tasks.Add(ScheduleExecuteCheckAsync(check), check.Id); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
363 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
364 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
365 } |
17 | 366 // Run again in case removing a task above caused it to stop. |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
367 Run(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
368 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
369 |
17 | 370 /// <summary>Handles the enabled state of a server changing.</summary> |
371 /// <param name="sender">The server that was enabled or disabled.</param> | |
4 | 372 private void Server_EnabledChanged(object sender, EventArgs e) |
373 { | |
374 Server server = (Server)sender; | |
17 | 375 |
376 // Make sure the monitor is running. If no servers were enabled before this | |
377 // one was enabled, it is not running. | |
4 | 378 if (server.Enabled) |
379 { | |
380 Run(); | |
381 } | |
382 else | |
383 { | |
17 | 384 // Cancel all queued and executing checks belonging to a |
385 // server that was disabled. | |
4 | 386 foreach (Check check in server.Checks) |
387 { | |
388 CancelCheck(check); | |
389 } | |
390 } | |
391 } | |
392 | |
17 | 393 /// <summary>Cancels a check that may be executing.</summary> |
394 /// <param name="check">The check to cancel.</param> | |
4 | 395 private void CancelCheck(Check check) |
396 { | |
6
c1dffaac66fa
- Don't show multiple password dialogs for the same key if the first one was cancelled.
Brad Greco <brad@bgreco.net>
parents:
5
diff
changeset
|
397 if (tasks == null) |
c1dffaac66fa
- Don't show multiple password dialogs for the same key if the first one was cancelled.
Brad Greco <brad@bgreco.net>
parents:
5
diff
changeset
|
398 return; |
17 | 399 |
400 // Find the waiting or executing task for the check and remove it. | |
4 | 401 Task<CheckResult> task = tasks.FirstOrDefault(kvp => kvp.Value == check.Id).Key; |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
402 if (task != null) |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
403 tasks.Remove(task); |
17 | 404 |
405 // Remove it from the list of paused checks so it doesn't get restarted later. | |
4 | 406 pausedChecks.RemoveAll(id => id == check.Id); |
17 | 407 |
408 // Cancel the current execution. | |
4 | 409 if (tokens.TryGetValue(check.Id, out CancellationTokenSource cts)) |
410 cts.Cancel(); | |
411 } | |
412 | |
17 | 413 /// <summary>Handles network state changing.</summary> |
4 | 414 private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) |
415 { | |
416 networkAvailable = Helpers.IsNetworkAvailable(); | |
17 | 417 // If the network is available, it might not have been before. |
418 // This method is not called from the correct thread, so special | |
419 // handling is needed to start it on the UI thread again. | |
4 | 420 if (networkAvailable) |
421 mainForm.Invoke((MethodInvoker)(() => Run())); | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
422 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
423 |
17 | 424 /// <summary>Handles system power mode changes.</summary> |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
425 private async void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
426 { |
17 | 427 // If the system is being suspended, cancel all waiting and executing checks. |
428 // Once all the checks are removed, the main loop will exit. | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
429 if (e.Mode == PowerModes.Suspend) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
430 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
431 foreach (Check check in Checks) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
432 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
433 CancelCheck(check); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
434 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
435 suspend = true; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
436 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
437 else if (e.Mode == PowerModes.Resume) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
438 { |
17 | 439 // When resuming from suspend, examine each check to find out if it was |
440 // scheduled to be executed during the time period when the systems was | |
441 // suspended. Add them to the paused checks list, to be executed almost | |
442 // immediately. | |
443 // Make sure the list is empty to start. | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
444 pausedChecks.Clear(); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
445 foreach (Check check in Checks) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
446 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
447 if (check.Enabled && check.Server.Enabled && check.NextRunTime < DateTime.Now) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
448 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
449 pausedChecks.Add(check.Id); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
450 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
451 } |
17 | 452 // Wait 10 seconds to give things time to quiet down after resuming. |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
453 await Task.Delay(10000); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
454 suspend = false; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
455 Run(); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
456 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
457 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
458 |
17 | 459 /// <summary>Unregister system events when exiting.</summary> |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
460 private void Application_ApplicationExit(object sender, EventArgs e) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
461 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
462 NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
463 SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
464 } |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
465 |
17 | 466 /// <summary>Attempts to read a private file.</summary> |
467 /// <param name="path">The path to the private key file.</param> | |
468 /// <param name="password">The password used to encrypt the key.</param> | |
469 /// <returns>A status indicating the result of the attempt.</returns> | |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
470 public KeyStatus OpenPrivateKey(string path, string password = null) |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
471 { |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
472 KeyStatus keyStatus; |
17 | 473 |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
474 if (path == null) |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
475 keyStatus = KeyStatus.NotAccessible; |
17 | 476 |
477 // Check if the key has already been open and read. | |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
478 if (privateKeys.TryGetValue(path, out PrivateKeyFile key) && key != null) |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
479 keyStatus = KeyStatus.Open; |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
480 else |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
481 { |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
482 try |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
483 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
484 key = new PrivateKeyFile(path, password); |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
485 keyStatus = KeyStatus.Open; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
486 } |
17 | 487 // If the key is encrypted and the password is empty or incorrect, |
488 // return the NeedPassword status. | |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
489 catch (Exception e) when (e is SshPassPhraseNullOrEmptyException || e is InvalidOperationException) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
490 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
491 keyStatus = KeyStatus.NeedPassword; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
492 } |
17 | 493 // For any other failure reason, return the NotAccessible status. |
8
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
494 catch (Exception) |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
495 { |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
496 keyStatus = KeyStatus.NotAccessible; |
052aa62cb42a
Single instance. Add autorun option. Add icons. General enhancements.
Brad Greco <brad@bgreco.net>
parents:
6
diff
changeset
|
497 } |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
498 } |
17 | 499 // A single private key may be used by multiple servers. Update all servers |
500 // that use this private key with the results of the above operations. | |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
501 foreach (Server server in Servers) |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
502 { |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
503 if (server.KeyFile == path) |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
504 { |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
505 server.PrivateKeyFile = key; |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
506 server.KeyStatus = keyStatus; |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
507 } |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
508 } |
17 | 509 // Keep a reference to this private key so we don't have to re-open |
510 // it later if the same key is used on a different server. | |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
511 privateKeys[path] = key; |
17 | 512 |
5
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
513 return keyStatus; |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
514 } |
b6fe203af9d5
Private key passwords and validation
Brad Greco <brad@bgreco.net>
parents:
4
diff
changeset
|
515 |
17 | 516 /// <summary>Generates internal IDs for servers and checks.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
517 private void GenerateIds() |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
518 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
519 if (Servers.Any()) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
520 { |
17 | 521 // Start at the maximum ID to make sure IDs are not reused |
522 // if a server was deleted so old log entries do not get associated | |
523 // with a new server. | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
524 int id = Servers.Max(s => s.Id); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
525 foreach (Server server in Servers) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
526 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
527 if (server.Id == 0) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
528 server.Id = ++id; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
529 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
530 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
531 |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
532 if (Checks.Any()) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
533 { |
17 | 534 // Start with the max check ID, same reasons as above. |
535 // Is there a reason this is stored in a setting? | |
4 | 536 int id = Math.Max(Settings.Default.MaxCheckId, Checks.Max(c => c.Id)); |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
537 foreach (Check check in Checks) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
538 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
539 if (check.Id == 0) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
540 check.Id = ++id; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
541 } |
4 | 542 Settings.Default.MaxCheckId = id; |
543 Settings.Default.Save(); | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
544 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
545 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
546 |
17 | 547 /// <summary>Creates an XML serializer that can handle servers and all check types.</summary> |
548 /// <returns>An XML serializer that can handle servers and all check types.</returns> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
549 private XmlSerializer CreateXmlSerializer() |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
550 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
551 return new XmlSerializer(typeof(List<Server>), Check.CheckTypes); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
552 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
553 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
554 |
17 | 555 /// <summary>Event arguments for when a check status changes.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
556 public class CheckStatusChangedEventArgs : EventArgs |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
557 { |
17 | 558 /// <summary>The check whose status changed.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
559 public Check Check { get; private set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
560 |
17 | 561 /// <summary>The check result that caused the status to change, if any.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
562 public CheckResult CheckResult { get; private set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
563 |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
564 public CheckStatusChangedEventArgs(Check check, CheckResult result) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
565 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
566 Check = check; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
567 CheckResult = result; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
568 } |
4 | 569 } |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
570 |
17 | 571 /// <summary>Possible actions that may be taken when a check fails.</summary> |
572 public enum FailAction | |
573 { | |
574 /// <summary>Flashes the Server Monitor tasbar program icon.</summary> | |
575 FlashTaskbar = 0, | |
576 /// <summary>Shows a balloon in the notification area.</summary> | |
577 NotificationBalloon = 1, | |
578 /// <summary>Take no action.</summary> | |
579 None = 10 | |
580 } | |
581 | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
582 } |