changeset 3:96f0b028176d

File check
author Brad Greco <brad@bgreco.net>
date Fri, 11 Jan 2019 22:34:18 -0500
parents 453ecc1ed9ea
children 3142e52cbe69
files ServerMonitor/Controls/DiskSpaceCheckControl.Designer.cs ServerMonitor/Controls/FileCheckControl.Designer.cs ServerMonitor/Controls/FileCheckControl.cs ServerMonitor/Controls/FileCheckControl.resx ServerMonitor/Controls/SizeUnitsComboBox.cs ServerMonitor/Controls/TimeUnitsComboBox.cs ServerMonitor/Objects/CheckResult.cs ServerMonitor/Objects/Checks/DiskSpaceCheck.cs ServerMonitor/Objects/Checks/FileCheck.cs ServerMonitor/Objects/Checks/SshCheck.cs ServerMonitor/ServerMonitor.csproj
diffstat 11 files changed, 640 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/ServerMonitor/Controls/DiskSpaceCheckControl.Designer.cs	Sun Jan 06 20:49:08 2019 -0500
+++ b/ServerMonitor/Controls/DiskSpaceCheckControl.Designer.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -28,35 +28,35 @@
         /// </summary>
         private void InitializeComponent()
         {
-            this.ResponseBodyPanel = new System.Windows.Forms.Panel();
+            this.FreeSpacePanel = new System.Windows.Forms.Panel();
             this.FreeSpaceUnitsComboBox = new System.Windows.Forms.ComboBox();
             this.FreeSpaceLabel = new System.Windows.Forms.Label();
             this.FreeSpaceTextBox = new System.Windows.Forms.TextBox();
             this.DeviceLabel = new System.Windows.Forms.Label();
             this.DeviceTextBox = new System.Windows.Forms.TextBox();
             this.CheckGroupBox.SuspendLayout();
-            this.ResponseBodyPanel.SuspendLayout();
+            this.FreeSpacePanel.SuspendLayout();
             this.SuspendLayout();
             // 
             // CheckGroupBox
             // 
-            this.CheckGroupBox.Controls.Add(this.ResponseBodyPanel);
+            this.CheckGroupBox.Controls.Add(this.FreeSpacePanel);
             this.CheckGroupBox.Controls.Add(this.DeviceLabel);
             this.CheckGroupBox.Controls.Add(this.DeviceTextBox);
             this.CheckGroupBox.Size = new System.Drawing.Size(526, 87);
             this.CheckGroupBox.Text = "null";
             // 
-            // ResponseBodyPanel
+            // FreeSpacePanel
             // 
-            this.ResponseBodyPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            this.FreeSpacePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
-            this.ResponseBodyPanel.Controls.Add(this.FreeSpaceUnitsComboBox);
-            this.ResponseBodyPanel.Controls.Add(this.FreeSpaceLabel);
-            this.ResponseBodyPanel.Controls.Add(this.FreeSpaceTextBox);
-            this.ResponseBodyPanel.Location = new System.Drawing.Point(9, 48);
-            this.ResponseBodyPanel.Name = "ResponseBodyPanel";
-            this.ResponseBodyPanel.Size = new System.Drawing.Size(511, 28);
-            this.ResponseBodyPanel.TabIndex = 21;
+            this.FreeSpacePanel.Controls.Add(this.FreeSpaceUnitsComboBox);
+            this.FreeSpacePanel.Controls.Add(this.FreeSpaceLabel);
+            this.FreeSpacePanel.Controls.Add(this.FreeSpaceTextBox);
+            this.FreeSpacePanel.Location = new System.Drawing.Point(9, 48);
+            this.FreeSpacePanel.Name = "FreeSpacePanel";
+            this.FreeSpacePanel.Size = new System.Drawing.Size(511, 28);
+            this.FreeSpacePanel.TabIndex = 21;
             // 
             // FreeSpaceUnitsComboBox
             // 
@@ -117,15 +117,15 @@
             this.Load += new System.EventHandler(this.DiskSpaceCheckControl_Load);
             this.CheckGroupBox.ResumeLayout(false);
             this.CheckGroupBox.PerformLayout();
-            this.ResponseBodyPanel.ResumeLayout(false);
-            this.ResponseBodyPanel.PerformLayout();
+            this.FreeSpacePanel.ResumeLayout(false);
+            this.FreeSpacePanel.PerformLayout();
             this.ResumeLayout(false);
 
         }
 
         #endregion
 
-        private System.Windows.Forms.Panel ResponseBodyPanel;
+        private System.Windows.Forms.Panel FreeSpacePanel;
         private System.Windows.Forms.TextBox FreeSpaceTextBox;
         private System.Windows.Forms.Label DeviceLabel;
         private System.Windows.Forms.TextBox DeviceTextBox;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Controls/FileCheckControl.Designer.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,223 @@
+namespace ServerMonitorApp
+{
+    partial class FileCheckControl
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.FileSizePanel = new System.Windows.Forms.Panel();
+            this.FileSizeUnitsComboBox = new ServerMonitorApp.SizeUnitsComboBox();
+            this.FileSizeComparisonComboBox = new System.Windows.Forms.ComboBox();
+            this.FileSizeCheckBox = new System.Windows.Forms.CheckBox();
+            this.FileSizeTextBox = new System.Windows.Forms.TextBox();
+            this.FileLabel = new System.Windows.Forms.Label();
+            this.FileTextBox = new System.Windows.Forms.TextBox();
+            this.FileModifiedPanel = new System.Windows.Forms.Panel();
+            this.DateModifiedComparisonComboBox = new System.Windows.Forms.ComboBox();
+            this.DateModifiedCheckBox = new System.Windows.Forms.CheckBox();
+            this.DateModifiedTextBox = new System.Windows.Forms.TextBox();
+            this.DateModifiedUnitsComboBox = new ServerMonitorApp.TimeUnitsComboBox();
+            this.CheckGroupBox.SuspendLayout();
+            this.FileSizePanel.SuspendLayout();
+            this.FileModifiedPanel.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // CheckGroupBox
+            // 
+            this.CheckGroupBox.Controls.Add(this.FileModifiedPanel);
+            this.CheckGroupBox.Controls.Add(this.FileSizePanel);
+            this.CheckGroupBox.Controls.Add(this.FileLabel);
+            this.CheckGroupBox.Controls.Add(this.FileTextBox);
+            this.CheckGroupBox.Size = new System.Drawing.Size(526, 114);
+            this.CheckGroupBox.Text = "null";
+            // 
+            // FileSizePanel
+            // 
+            this.FileSizePanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.FileSizePanel.Controls.Add(this.FileSizeUnitsComboBox);
+            this.FileSizePanel.Controls.Add(this.FileSizeComparisonComboBox);
+            this.FileSizePanel.Controls.Add(this.FileSizeCheckBox);
+            this.FileSizePanel.Controls.Add(this.FileSizeTextBox);
+            this.FileSizePanel.Location = new System.Drawing.Point(9, 48);
+            this.FileSizePanel.Name = "FileSizePanel";
+            this.FileSizePanel.Size = new System.Drawing.Size(511, 28);
+            this.FileSizePanel.TabIndex = 21;
+            // 
+            // FileSizeUnitsComboBox
+            // 
+            this.FileSizeUnitsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.FileSizeUnitsComboBox.FormattingEnabled = true;
+            this.FileSizeUnitsComboBox.Items.AddRange(new object[] {
+            "B",
+            "MB",
+            "KB",
+            "GB"});
+            this.FileSizeUnitsComboBox.Location = new System.Drawing.Point(227, 4);
+            this.FileSizeUnitsComboBox.Name = "FileSizeUnitsComboBox";
+            this.FileSizeUnitsComboBox.Size = new System.Drawing.Size(43, 21);
+            this.FileSizeUnitsComboBox.TabIndex = 26;
+            // 
+            // FileSizeComparisonComboBox
+            // 
+            this.FileSizeComparisonComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.FileSizeComparisonComboBox.FormattingEnabled = true;
+            this.FileSizeComparisonComboBox.Items.AddRange(new object[] {
+            "less than",
+            "greater than"});
+            this.FileSizeComparisonComboBox.Location = new System.Drawing.Point(63, 4);
+            this.FileSizeComparisonComboBox.Name = "FileSizeComparisonComboBox";
+            this.FileSizeComparisonComboBox.Size = new System.Drawing.Size(83, 21);
+            this.FileSizeComparisonComboBox.TabIndex = 25;
+            // 
+            // FileSizeCheckBox
+            // 
+            this.FileSizeCheckBox.AutoSize = true;
+            this.FileSizeCheckBox.Location = new System.Drawing.Point(0, 6);
+            this.FileSizeCheckBox.Name = "FileSizeCheckBox";
+            this.FileSizeCheckBox.Size = new System.Drawing.Size(63, 17);
+            this.FileSizeCheckBox.TabIndex = 24;
+            this.FileSizeCheckBox.Text = "File size";
+            this.FileSizeCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // FileSizeTextBox
+            // 
+            this.FileSizeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.FileSizeTextBox.Location = new System.Drawing.Point(152, 4);
+            this.FileSizeTextBox.Name = "FileSizeTextBox";
+            this.FileSizeTextBox.Size = new System.Drawing.Size(69, 20);
+            this.FileSizeTextBox.TabIndex = 7;
+            // 
+            // FileLabel
+            // 
+            this.FileLabel.AutoSize = true;
+            this.FileLabel.Location = new System.Drawing.Point(6, 25);
+            this.FileLabel.Name = "FileLabel";
+            this.FileLabel.Size = new System.Drawing.Size(26, 13);
+            this.FileLabel.TabIndex = 18;
+            this.FileLabel.Text = "File:";
+            // 
+            // FileTextBox
+            // 
+            this.FileTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.FileTextBox.Location = new System.Drawing.Point(38, 22);
+            this.FileTextBox.Name = "FileTextBox";
+            this.FileTextBox.Size = new System.Drawing.Size(482, 20);
+            this.FileTextBox.TabIndex = 17;
+            this.FileTextBox.Text = "/";
+            // 
+            // FileModifiedPanel
+            // 
+            this.FileModifiedPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.FileModifiedPanel.Controls.Add(this.DateModifiedUnitsComboBox);
+            this.FileModifiedPanel.Controls.Add(this.DateModifiedComparisonComboBox);
+            this.FileModifiedPanel.Controls.Add(this.DateModifiedCheckBox);
+            this.FileModifiedPanel.Controls.Add(this.DateModifiedTextBox);
+            this.FileModifiedPanel.Location = new System.Drawing.Point(9, 75);
+            this.FileModifiedPanel.Name = "FileModifiedPanel";
+            this.FileModifiedPanel.Size = new System.Drawing.Size(511, 28);
+            this.FileModifiedPanel.TabIndex = 27;
+            // 
+            // DateModifiedComparisonComboBox
+            // 
+            this.DateModifiedComparisonComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.DateModifiedComparisonComboBox.FormattingEnabled = true;
+            this.DateModifiedComparisonComboBox.Items.AddRange(new object[] {
+            "older than",
+            "newer than"});
+            this.DateModifiedComparisonComboBox.Location = new System.Drawing.Point(91, 4);
+            this.DateModifiedComparisonComboBox.Name = "DateModifiedComparisonComboBox";
+            this.DateModifiedComparisonComboBox.Size = new System.Drawing.Size(82, 21);
+            this.DateModifiedComparisonComboBox.TabIndex = 25;
+            // 
+            // DateModifiedCheckBox
+            // 
+            this.DateModifiedCheckBox.AutoSize = true;
+            this.DateModifiedCheckBox.Location = new System.Drawing.Point(0, 6);
+            this.DateModifiedCheckBox.Name = "DateModifiedCheckBox";
+            this.DateModifiedCheckBox.Size = new System.Drawing.Size(91, 17);
+            this.DateModifiedCheckBox.TabIndex = 24;
+            this.DateModifiedCheckBox.Text = "Date modified";
+            this.DateModifiedCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // DateModifiedTextBox
+            // 
+            this.DateModifiedTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.DateModifiedTextBox.Location = new System.Drawing.Point(179, 4);
+            this.DateModifiedTextBox.Name = "DateModifiedTextBox";
+            this.DateModifiedTextBox.Size = new System.Drawing.Size(69, 20);
+            this.DateModifiedTextBox.TabIndex = 7;
+            // 
+            // DateModifiedUnitsComboBox
+            // 
+            this.DateModifiedUnitsComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.DateModifiedUnitsComboBox.FormattingEnabled = true;
+            this.DateModifiedUnitsComboBox.Items.AddRange(new object[] {
+            "minutes",
+            "hours",
+            "days"});
+            this.DateModifiedUnitsComboBox.Location = new System.Drawing.Point(254, 4);
+            this.DateModifiedUnitsComboBox.Name = "DateModifiedUnitsComboBox";
+            this.DateModifiedUnitsComboBox.Size = new System.Drawing.Size(60, 21);
+            this.DateModifiedUnitsComboBox.TabIndex = 26;
+            // 
+            // FileCheckControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Name = "FileCheckControl";
+            this.Size = new System.Drawing.Size(526, 114);
+            this.Load += new System.EventHandler(this.DiskSpaceCheckControl_Load);
+            this.CheckGroupBox.ResumeLayout(false);
+            this.CheckGroupBox.PerformLayout();
+            this.FileSizePanel.ResumeLayout(false);
+            this.FileSizePanel.PerformLayout();
+            this.FileModifiedPanel.ResumeLayout(false);
+            this.FileModifiedPanel.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel FileSizePanel;
+        private System.Windows.Forms.TextBox FileSizeTextBox;
+        private System.Windows.Forms.Label FileLabel;
+        private System.Windows.Forms.TextBox FileTextBox;
+        private System.Windows.Forms.CheckBox FileSizeCheckBox;
+        private System.Windows.Forms.ComboBox FileSizeComparisonComboBox;
+        private SizeUnitsComboBox FileSizeUnitsComboBox;
+        private System.Windows.Forms.Panel FileModifiedPanel;
+        private System.Windows.Forms.ComboBox DateModifiedComparisonComboBox;
+        private System.Windows.Forms.CheckBox DateModifiedCheckBox;
+        private System.Windows.Forms.TextBox DateModifiedTextBox;
+        private TimeUnitsComboBox DateModifiedUnitsComboBox;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Controls/FileCheckControl.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace ServerMonitorApp
+{
+    [CheckType(typeof(FileCheck))]
+    public partial class FileCheckControl : CheckControl
+    {
+        public FileCheckControl()
+        {
+            InitializeComponent();
+        }
+
+        private void DiskSpaceCheckControl_Load(object sender, EventArgs e)
+        {
+            FileSizeComparisonComboBox.SelectedIndex = 0;
+            DateModifiedComparisonComboBox.SelectedIndex = 0;
+        }
+
+        public override void LoadCheck(Check check1)
+        {
+            FileCheck check = (FileCheck)check1;
+            FileTextBox.Text = check.File;
+            FileSizeCheckBox.Checked = check.CheckFileSize;
+            FileSizeComparisonComboBox.SelectedIndex = check.FileSizeLessThan ? 0 : 1;
+            FileSizeTextBox.Text = check.FileSizeInSelectedUnits.ToString();
+            FileSizeUnitsComboBox.SelectedIndex = (int)check.FileSizeUnits;
+            DateModifiedCheckBox.Checked = check.CheckDateModified;
+            DateModifiedComparisonComboBox.SelectedIndex = check.DateModifiedOlderThan ? 0 : 1;
+            DateModifiedTextBox.Text = check.DateModified.ToString();
+            DateModifiedUnitsComboBox.SelectedIndex = (int)check.DateModifiedUnits;
+
+            if (FileSizeTextBox.Text == "0")
+                FileSizeTextBox.Clear();
+            if (DateModifiedTextBox.Text == "0")
+                DateModifiedTextBox.Clear();
+        }
+
+        public override void UpdateCheck(Check check1)
+        {
+            FileCheck check = (FileCheck)check1;
+            check.File = FileTextBox.Text;
+            check.CheckFileSize = FileSizeCheckBox.Checked;
+            check.FileSizeLessThan = FileSizeComparisonComboBox.SelectedIndex == 0;
+            try
+            {
+                check.FileSizeInSelectedUnits = double.Parse(FileSizeTextBox.Text);
+            }
+            catch
+            {
+                if (check.CheckFileSize)
+                    throw new UpdateCheckException("File size must be numeric.");
+                else
+                    check.FileSizeInSelectedUnits = 0;
+            }
+            check.FileSizeUnits = (SizeUnits)FileSizeUnitsComboBox.SelectedIndex;
+            check.CheckDateModified = DateModifiedCheckBox.Checked;
+            check.DateModifiedOlderThan = DateModifiedComparisonComboBox.SelectedIndex == 0;
+            try
+            {
+                check.DateModified = double.Parse(DateModifiedTextBox.Text);
+            }
+            catch
+            {
+                if (check.CheckDateModified)
+                    throw new UpdateCheckException("Date modified must be numeric.");
+                else
+                    check.DateModified = 0;
+            }
+            check.DateModifiedUnits = (TimeUnits)DateModifiedUnitsComboBox.SelectedIndex;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Controls/FileCheckControl.resx	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Controls/SizeUnitsComboBox.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace ServerMonitorApp
+{
+    class SizeUnitsComboBox : ComboBox
+    {
+        protected override void OnCreateControl()
+        {
+            base.OnCreateControl();
+            Items.Clear();
+            Items.Add("B");
+            Items.Add("KB");
+            Items.Add("MB");
+            Items.Add("GB");
+            SelectedIndex = 0;
+        }
+    }
+
+    public enum SizeUnits { B = 0, KB = 1, MB = 2, GB = 3 }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Controls/TimeUnitsComboBox.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace ServerMonitorApp
+{
+    class TimeUnitsComboBox : ComboBox
+    {
+        protected override void OnCreateControl()
+        {
+            base.OnCreateControl();
+            Items.Clear();
+            Items.Add("minutes");
+            Items.Add("hours");
+            Items.Add("days");
+            SelectedIndex = 2;
+        }
+    }
+
+    public enum TimeUnits { Minute = 0, Hour = 1, Day = 2 }
+}
--- a/ServerMonitor/Objects/CheckResult.cs	Sun Jan 06 20:49:08 2019 -0500
+++ b/ServerMonitor/Objects/CheckResult.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -12,7 +12,7 @@
 
         public CheckStatus CheckStatus { get; private set; }
 
-        public string Message { get; private set; }
+        public string Message { get; set; }
 
         public DateTime StartTime { get; set; }
 
--- a/ServerMonitor/Objects/Checks/DiskSpaceCheck.cs	Sun Jan 06 20:49:08 2019 -0500
+++ b/ServerMonitor/Objects/Checks/DiskSpaceCheck.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -10,6 +10,8 @@
     [DisplayName("Disk space check"), Description("Check the remaining free disk space"), DisplayWeight(11)]
     public class DiskSpaceCheck : SshCheck
     {
+        public override string Command { get => string.Format(base.Command, Device); }
+
         public string Device { get; set; }
 
         public double MinFreeSpace { get; set; }
@@ -18,30 +20,30 @@
 
         public DiskSpaceCheck()
         {
-            Command = "df -P -k {0} | awk 'NR>1' | tr -s ' ' | cut -d ' ' -f 4,5";
+            //Command = "df -P -k {0} | awk 'NR>1' | tr -s ' ' | cut -d ' ' -f 4,5";
+            Command = "df -P -k {0}";
             CheckExitCode = true;
             ExitCode = 0;
         }
 
-        protected override string GetCommand()
-        {
-            return string.Format(base.GetCommand(), Device);
-        }
-
         protected override List<CheckResult> ProcessCommandResult(string output, int exitCode)
         {
             List<CheckResult> results = base.ProcessCommandResult(output, exitCode);
-            if (output.Split('\n').Length > 1)
+            if (results.Any(r => r.CheckStatus != CheckStatus.Success))
+                return results;
+
+            List<string> lines = output.Split('\n').ToList();
+            lines.RemoveAt(0);
+            if (lines.Count > 1)
             {
-                results.Add(Fail("df output was more than one line: " + output));
+                results.Add(Fail("df output was more than one line: " + string.Join("\n", lines)));
             }
             else
             {
-
-                string[] tokens = output.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
+                string[] tokens = lines[0].Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
                 if (FreeSpaceUnits == FreeSpaceUnits.percent)
                 {
-                    if (int.TryParse(tokens[1].Replace("%", ""), out int percent))
+                    if (int.TryParse(tokens[4].Replace("%", ""), out int percent))
                     {
                         percent = 100 - percent;
                         string message = string.Format("Free disk space is {0}%", percent);
@@ -52,12 +54,12 @@
                     }
                     else
                     {
-                        results.Add(Fail("Unable to parse df output as integer: " + tokens[1].Replace("%", "")));
+                        results.Add(Fail("Unable to parse df output as integer: " + tokens[4].Replace("%", "")));
                     }
                 }
                 else
                 {
-                    if (int.TryParse(tokens[0], out int freeSpace))
+                    if (int.TryParse(tokens[3], out int freeSpace))
                     {
                         freeSpace /= 1024;
                         if (FreeSpaceUnits == FreeSpaceUnits.GB)
@@ -70,7 +72,7 @@
                     }
                     else
                     {
-                        results.Add(Fail("Unable to parse df output as integer: " + tokens[0]));
+                        results.Add(Fail("Unable to parse df output as integer: " + tokens[3]));
                     }
                 }
             }
@@ -91,4 +93,4 @@
     }
 
     public enum FreeSpaceUnits { MB = 0, GB = 1, percent = 2 }
-}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerMonitor/Objects/Checks/FileCheck.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace ServerMonitorApp
+{
+    [DisplayName("File check"), Description("Check file size or modified time"), DisplayWeight(12)]
+    public class FileCheck : SshCheck
+    {
+        public override string Command { get => string.Format(base.Command, Regex.Replace(File, "^~", "$HOME")); }
+
+        public string File { get; set; }
+
+        public bool CheckFileSize { get; set; }
+
+        public bool FileSizeLessThan { get; set; }
+
+        public double FileSize { get; set; }
+
+        public double FileSizeInSelectedUnits
+        {
+            get { return FileSize / Math.Pow(1024, (double)FileSizeUnits); }
+            set { FileSize = value * Math.Pow(1024, (double)FileSizeUnits); }
+        }
+
+        public SizeUnits FileSizeUnits { get; set; }
+
+        public bool CheckDateModified { get; set; }
+
+        public bool DateModifiedOlderThan { get; set; }
+
+        public double DateModified { get; set; }
+
+        public TimeUnits DateModifiedUnits { get; set; }
+
+        public FileCheck()
+        {
+            Command = "export TIME_STYLE=long-iso; ls -l \"{0}\"";
+            //Command = "export TIME_STYLE=long-iso; ls -l \"{0}\" | tr -s ' ' | cut -d ' ' -f 5,6,7";
+            CheckExitCode = true;
+            ExitCode = 0;
+        }
+
+        protected override List<CheckResult> ProcessCommandResult(string output, int exitCode)
+        {
+            List<CheckResult> results = base.ProcessCommandResult(output, exitCode);
+            if (results.Any(r => r.CheckStatus != CheckStatus.Success))
+                return results;
+
+            if (output.Split('\n').Length > 1)
+            {
+                results.Add(Fail("ls output was more than one line: " + output));
+            }
+            else
+            {
+                string[] tokens = output.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
+                if (CheckFileSize)
+                {
+                    if (int.TryParse(tokens[4], out int bytes))
+                    {
+                        string message = string.Format("File size is {0} {1}", bytes / Math.Pow(1024, (double)FileSizeUnits), FileSizeUnits);
+                        if ((bytes < FileSize && FileSizeLessThan) || (bytes > FileSize && !FileSizeLessThan))
+                            results.Add(Pass(message));
+                        else
+                            results.Add(Fail(message));
+                    }
+                    else
+                    {
+                        results.Add(Fail("Unable to parse ls output as integer: " + tokens[4]));
+                    }
+                }
+                if (CheckDateModified)
+                {
+                    string dateString = tokens[5] + " " + tokens[6];
+                    if (DateTime.TryParse(dateString, out DateTime modified))
+                    {
+                        string message = string.Format("Last modified date is {0}", modified);
+                        TimeSpan age = DateTime.Now.Subtract(modified);
+                        double ageCompare = DateModifiedUnits == TimeUnits.Minute ? age.TotalMinutes :
+                                         DateModifiedUnits == TimeUnits.Hour ? age.TotalHours :
+                                         age.TotalDays;
+                        if ((ageCompare > DateModified && DateModifiedOlderThan) || (ageCompare < DateModified && !DateModifiedOlderThan))
+                            results.Add(Pass(message));
+                        else
+                            results.Add(Fail(message));
+                    }
+                    else
+                    {
+                        results.Add(Fail("Unable to parse ls output as date: " + dateString));
+                    }
+                }
+            }
+            return results;
+        }
+
+        public override string Validate(bool saving = true)
+        {
+            string message = base.Validate();
+            if (File.IsNullOrEmpty())
+                message += "File is required." + Environment.NewLine;
+            if (!CheckFileSize && !CheckDateModified)
+                message += "At least one check must be enabled." + Environment.NewLine;
+            if (CheckFileSize && FileSize <= 0)
+                message += "File size must be greater than 0." + Environment.NewLine;
+            if (CheckDateModified && DateModified <= 0)
+                message += "Date modified must be greater than 0." + Environment.NewLine;
+            return message;
+        }
+    }
+}
\ No newline at end of file
--- a/ServerMonitor/Objects/Checks/SshCheck.cs	Sun Jan 06 20:49:08 2019 -0500
+++ b/ServerMonitor/Objects/Checks/SshCheck.cs	Fri Jan 11 22:34:18 2019 -0500
@@ -13,7 +13,7 @@
     [DisplayName("SSH check"), Description("Check the result of a command run over SSH"), DisplayWeight(10)]
     public class SshCheck : Check
     {
-        public string Command { get; set; }
+        public virtual string Command { get; set; }
 
         public bool CheckExitCode { get; set; }
 
@@ -36,7 +36,7 @@
                     if (!Server.SshClient.IsConnected)
                         Server.SshClient.Connect();
                     token.ThrowIfCancellationRequested();
-                    using (SshCommand command = Server.SshClient.CreateCommand(GetCommand()))
+                    using (SshCommand command = Server.SshClient.CreateCommand(Command))
                     {
                         token.Register(command.CancelAsync);
                         IAsyncResult ar = command.BeginExecute();
@@ -68,16 +68,16 @@
             //return tcs.Task;
         }
 
-        protected virtual string GetCommand()
-        {
-            return Command;
-        }
-
         protected virtual List<CheckResult> ProcessCommandResult(string output, int exitCode)
         {
             List<CheckResult> results = new List<CheckResult>();
             if (CheckExitCode)
-                results.Add(GetIntResult(ExitCode, exitCode, "Exit code"));
+            {
+                CheckResult result = GetIntResult(ExitCode, exitCode, "Exit code");
+                if (result.CheckStatus != CheckStatus.Success)
+                    result.Message += ". Command output: " + output;
+                results.Add(result);
+            }
             if (CheckCommandOutput)
                 results.Add(GetStringResult(CommandOutputMatchType, CommandOutputPattern, CommandOutputUseRegex, output, "Command output"));
             return results;
--- a/ServerMonitor/ServerMonitor.csproj	Sun Jan 06 20:49:08 2019 -0500
+++ b/ServerMonitor/ServerMonitor.csproj	Fri Jan 11 22:34:18 2019 -0500
@@ -62,12 +62,24 @@
     <Compile Include="Controls\CheckControl.Designer.cs">
       <DependentUpon>CheckControl.cs</DependentUpon>
     </Compile>
+    <Compile Include="Controls\FileCheckControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\FileCheckControl.Designer.cs">
+      <DependentUpon>FileCheckControl.cs</DependentUpon>
+    </Compile>
     <Compile Include="Controls\DiskSpaceCheckControl.cs">
       <SubType>UserControl</SubType>
     </Compile>
     <Compile Include="Controls\DiskSpaceCheckControl.Designer.cs">
       <DependentUpon>DiskSpaceCheckControl.cs</DependentUpon>
     </Compile>
+    <Compile Include="Controls\TimeUnitsComboBox.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Controls\SizeUnitsComboBox.cs">
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="Controls\SshCheckControl.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -83,6 +95,7 @@
     <Compile Include="Controls\MatchComboBox.cs">
       <SubType>Component</SubType>
     </Compile>
+    <Compile Include="Objects\Checks\FileCheck.cs" />
     <Compile Include="Objects\Checks\DiskSpaceCheck.cs" />
     <Compile Include="Objects\UpdateCheckException.cs" />
     <Compile Include="Forms\CheckBoxDialog.cs">
@@ -136,6 +149,9 @@
     <EmbeddedResource Include="Controls\CheckControl.resx">
       <DependentUpon>CheckControl.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Controls\FileCheckControl.resx">
+      <DependentUpon>FileCheckControl.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Controls\DiskSpaceCheckControl.resx">
       <DependentUpon>DiskSpaceCheckControl.cs</DependentUpon>
     </EmbeddedResource>