comparison ServerMonitor/Forms/CheckForm.cs @ 0:3e1a2131f897

Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
author Brad Greco <brad@bgreco.net>
date Mon, 31 Dec 2018 18:32:14 -0500
parents
children 9e92780ebc0f
comparison
equal deleted inserted replaced
-1:000000000000 0:3e1a2131f897
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Threading;
9 using System.Windows.Forms;
10
11 namespace ServerMonitorApp
12 {
13 public partial class CheckForm : Form
14 {
15 //private static readonly Dictionary<Type, CheckInfo> checkInfo = new Dictionary<Type, CheckInfo>();
16 private readonly List<CheckControl> checkControls = new List<CheckControl>();
17 private bool helpShown;
18 private CancellationTokenSource cancellationTokenSource;
19 private Check workCheck;
20 private CheckControl checkControl;
21 private QuickHelpForm helpForm;
22 private Server server;
23 private ServerMonitor monitor;
24
25 public event EventHandler<HelpLocationChangedEventArgs> HelpLocationChanged;
26
27 public Check Check { get; private set; }
28
29 public int CheckId { get; private set; }
30
31 public Point HelpLocation { get { return TypeHelpPictureBox.PointToScreen(Point.Empty); } }
32
33 public CheckForm(ServerMonitor monitor, Check check)
34 {
35 InitializeComponent();
36
37 Check = check;
38 CheckId = Check.Id;
39 server = Check.Server;
40 this.monitor = monitor;
41 }
42
43 public CheckForm(ServerMonitor monitor, Server server)
44 {
45 InitializeComponent();
46 this.server = server;
47 this.monitor = monitor;
48 }
49
50 private void CheckForm_Load(object sender, EventArgs e)
51 {
52 CheckTypeComboBox.Items.AddRange(Check.CheckTypes);
53 FrequencyUnitsComboBox.DataSource = Enum.GetValues(typeof(FrequencyUnits));
54 Helpers.FormatImageButton(RunButton);
55 Helpers.FormatImageButton(CancelRunButton);
56
57 Move += CheckForm_Move;
58 CheckTypePanel.LocationChanged += CheckTypePanel_LocationChanged;
59 GeneralGroupBox.Click += Control_Click;
60 CheckSettingsPanel.Click += Control_Click;
61
62 CheckTypeComboBox.SelectedItem = Check?.GetType();
63 if (Check != null)
64 LoadCheck(Check);
65 }
66
67 private void CheckTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
68 {
69 ShowCheckControl();
70 workCheck = (Check)Activator.CreateInstance((Type)CheckTypeComboBox.SelectedItem);
71 }
72
73 private void CheckTypeComboBox_Format(object sender, ListControlConvertEventArgs e)
74 {
75 e.Value = Helpers.GetDisplayName((Type)e.ListItem);
76 }
77
78 /*private void showGroupBox(GroupBox groupBox)
79 {
80
81 }*/
82
83 /*private Type GetCheckType()
84 {
85 return (Type)CheckTypeComboBox.SelectedItem;
86 }*/
87
88 private void ShowCheckControl()
89 {
90 IEnumerable<CheckControl> checkControls = CheckSettingsPanel.Controls.OfType<CheckControl>();
91 foreach (CheckControl control in checkControls)
92 control.Hide();
93 Type type = (Type)CheckTypeComboBox.SelectedItem;
94 checkControl = checkControls.FirstOrDefault(c => c.CheckType == type);
95 if (checkControl == null)
96 {
97 checkControl = CheckControl.Create(type);
98 if (checkControl != null)
99 {
100 checkControl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
101 checkControl.Click += Control_Click;
102 CheckSettingsPanel.Controls.Add(checkControl);
103 }
104 }
105 if (checkControl != null)
106 {
107 CheckSettingsPanel.Height = checkControl.Height;
108 //Height = 230 + checkControl.Height;
109 checkControl.Show();
110 }
111 }
112
113 private void LoadCheck(Check check)
114 {
115 NameTextBox.Text = Check.Name;
116 EnabledCheckBox.Checked = check.Enabled;
117 TimeoutInput.Value = check.Timeout;
118 FrequencyUnitsComboBox.SelectedItem = check.Schedule.Units;
119 FrequencyUpDown.Value = check.Schedule.Frequency;
120 StartTimePicker.Value = new DateTime(1970, 1, 1) + check.Schedule.StartTime;
121 EndTimePicker.Value = new DateTime(1970, 1, 1) + check.Schedule.EndTime;
122 checkControl?.LoadCheck(check);
123 }
124
125 private bool UpdateCheck(Check check, bool saving = true)
126 {
127 string result;
128 if (CheckTypeComboBox.SelectedIndex == -1)
129 {
130 result = "Check type cannot be blank.";
131 }
132 else
133 {
134 check.Id = CheckId;
135 check.Server = server;
136 check.Name = NameTextBox.Text;
137 check.Enabled = EnabledCheckBox.Checked;
138 check.Timeout = (int)TimeoutInput.Value;
139 check.Schedule = new Schedule((FrequencyUnits)FrequencyUnitsComboBox.SelectedItem, (int)FrequencyUpDown.Value, StartTimePicker.Value.TimeOfDay, EndTimePicker.Value.TimeOfDay);
140 checkControl?.UpdateCheck(check);
141 result = check.Validate(saving);
142 }
143 if (!result.IsNullOrEmpty())
144 {
145 MessageBox.Show(result, "Error validating check", MessageBoxButtons.OK, MessageBoxIcon.Error);
146 return false;
147 }
148 return true;
149 }
150
151 private void OkButton_Click(object sender, EventArgs e)
152 {
153 if (!UpdateCheck(workCheck))
154 return;
155 Check = workCheck;
156 server.UpdateCheck(Check);
157 monitor.SaveServers();
158 Close();
159 }
160
161 private void CancelCheckButton_Click(object sender, EventArgs e)
162 {
163 Close();
164 }
165
166 private async void RunButton_Click(object sender, EventArgs e)
167 {
168 if (!UpdateCheck(workCheck, false))
169 return;
170
171 RunButton.Enabled = false;
172 RunButton.Text = "Running";
173 ResultLabel.Visible = ResultIconPictureBox.Visible = false;
174 CancelRunButton.Visible = true;
175
176 // Create a CancellationTokenSource for this execution, and set it to both variables.
177 // localCancellationTokenSource will mantain a reference to the token for this execution,
178 // while cancellationTokenSource might end up referencing a different token if the Cancel
179 // button is clicked (but the Task itself is unable to be cancelled), then Run is clicked
180 // again.
181 CancellationTokenSource localCancellationTokenSource = new CancellationTokenSource();
182 cancellationTokenSource = localCancellationTokenSource;
183 CheckResult result = await workCheck.ExecuteAsync(cancellationTokenSource.Token, false);
184 if (!localCancellationTokenSource.IsCancellationRequested)
185 OnRunFinished(result);
186 localCancellationTokenSource.Dispose();
187 localCancellationTokenSource = null;
188 }
189
190 //private void RunButton_Click(object sender, EventArgs e)
191 //{
192 // if (!Check.Server.SshClient.IsConnected)
193 // Check.Server.SshClient.Connect();
194 // using (Renci.SshNet.SshCommand command = Check.Server.SshClient.CreateCommand("ls"))
195 // {
196 // //token.Register(command.CancelAsync);
197 // //command.BeginExecute(asyncResult =>
198 // //{
199 // // string result = command.EndExecute(asyncResult);
200 // // //tcs.SetResult(new CheckResult(this, CheckStatus.Success, result));
201 // //});
202 // IAsyncResult iar = command.BeginExecute(z);
203 // command.EndExecute(iar);
204 // //string result = command.Execute();
205 // //System.Console.Write(result);
206 // }
207 //}
208
209 //private void z(IAsyncResult ar)
210 //{
211 // throw new NotImplementedException();
212 //}
213
214 private void CancelRunButton_Click(object sender, EventArgs e)
215 {
216 cancellationTokenSource.Cancel();
217 OnRunFinished();
218 }
219
220 /// <summary>Updates the UI after a check is finished running.</summary>
221 /// <param name="result">Result of the check execution. If null, the check was cancelled before it completed.</param>
222 private void OnRunFinished(CheckResult result = null)
223 {
224 RunButton.Enabled = true;
225 RunButton.Text = "Run";
226 CancelRunButton.Visible = false;
227 if (result != null)
228 {
229 ResultLabel.Text = result.Message;
230 //ResultLabel.ForeColor = result.CheckStatus == CheckStatus.Success ? Color.Green : Color.Red;
231 ResultIconPictureBox.Image = result.CheckStatus.GetIcon();
232 ResultLabel.Visible = ResultIconPictureBox.Visible = true;
233 }
234 }
235
236 /*private class CheckInfo
237 {
238 public GroupBox GroupBox { get; private set; }
239
240 public Func<string> ValidateFunction { get; private set; }
241
242 public CheckInfo(GroupBox groupBox, Func<string> validateFunction)
243 {
244 GroupBox = groupBox;
245 ValidateFunction = validateFunction;
246 }
247 }*/
248
249 private string BuildHelpText()
250 {
251 StringBuilder rtf = new StringBuilder(@"{\rtf1\ansi ");
252 foreach (Type checkType in Check.CheckTypes)
253 {
254 // Arguments to AppendLine() must end with a \ for the RichTextBox to render the newline character
255 rtf.Append(@"\b ").Append(Helpers.GetDisplayName(checkType)).AppendLine(@"\b0 \")
256 .Append(checkType.GetAttribute<DescriptionAttribute>()?.Description ?? "No description provided.").AppendLine(@"\").AppendLine(@"\");
257 }
258 return rtf.ToString().TrimEnd(' ', '\r', '\n', '\\');
259 }
260
261 private void TypeHelpPictureBox_Click(object sender, EventArgs e)
262 {
263 if (helpShown)
264 {
265 helpForm.Close();
266 }
267 else
268 {
269 helpForm = new QuickHelpForm(BuildHelpText());
270 helpForm.FormClosed += QuickHelpForm_FormClosed;
271 helpForm.Show(this);
272 Activate();
273 helpShown = true;
274 OnHelpLocationChanged();
275 }
276 }
277
278 private void QuickHelpForm_FormClosed(object sender, FormClosedEventArgs e)
279 {
280 helpShown = false;
281 helpForm.FormClosed -= QuickHelpForm_FormClosed;
282 helpForm.Dispose();
283 }
284
285 private void OnHelpLocationChanged()
286 {
287 HelpLocationChanged?.Invoke(this, new HelpLocationChangedEventArgs(HelpLocation));
288 }
289
290 private void CheckTypePanel_LocationChanged(object sender, EventArgs e)
291 {
292 OnHelpLocationChanged();
293 }
294
295 private void CheckForm_Move(object sender, EventArgs e)
296 {
297 OnHelpLocationChanged();
298 }
299
300 private void Control_Click(object sender, EventArgs e)
301 {
302 if (helpShown)
303 helpForm.Close();
304 }
305
306 protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
307 {
308 if (keyData == Keys.Escape && helpShown)
309 {
310 helpForm.Close();
311 return true;
312 }
313 return base.ProcessCmdKey(ref msg, keyData);
314 }
315
316 private void FrequencyUnitsComboBox_SelectedIndexChanged(object sender, EventArgs e)
317 {
318 ScheduleBetweenPanel.Visible = !(ScheduleAtPanel.Visible = FrequencyUnitsComboBox.SelectedIndex == 3);
319 }
320
321 private void FrequencyUnitsComboBox_Format(object sender, ListControlConvertEventArgs e)
322 {
323 e.Value = e.Value.ToString().ToLower() + 's';
324 }
325 }
326
327 public class HelpLocationChangedEventArgs : EventArgs
328 {
329 public Point HelpLocation { get; private set; }
330
331 public HelpLocationChangedEventArgs(Point helpLocation)
332 {
333 HelpLocation = helpLocation;
334 }
335 }
336 }