diff --git a/TimedShutdown.sln b/TimedShutdown.sln
index 0ae9497..00039df 100644
--- a/TimedShutdown.sln
+++ b/TimedShutdown.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2027
+VisualStudioVersion = 15.0.27004.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimedShutdown", "TimedShutdown\TimedShutdown.csproj", "{C1158C45-7666-4586-A6DA-CCC1EE95D457}"
EndProject
diff --git a/TimedShutdown/Messaging.cs b/TimedShutdown/Messaging.cs
new file mode 100644
index 0000000..7382da6
--- /dev/null
+++ b/TimedShutdown/Messaging.cs
@@ -0,0 +1,26 @@
+using System.Windows;
+
+namespace TimedShutdown
+{
+ public class Messaging
+ {
+ public enum Message
+ {
+ RemoteShutdown
+ }
+
+ public void Show(Message message, string info)
+ {
+ switch (message)
+ {
+ case Message.RemoteShutdown:
+ MessageBox.Show(
+ $"The following remote machine has been sent a shutdown/reboot signal:\n\n{info}",
+ "Timed Shutdown",
+ MessageBoxButton.OK,
+ MessageBoxImage.Information);
+ break;
+ }
+ }
+ }
+}
diff --git a/TimedShutdown/PingWidget.cs b/TimedShutdown/PingWidget.cs
new file mode 100644
index 0000000..f03c876
--- /dev/null
+++ b/TimedShutdown/PingWidget.cs
@@ -0,0 +1,50 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Threading;
+
+namespace TimedShutdown
+{
+ public class PingWidget
+ {
+ IPAddress _ipAddress = IPAddress.None;
+ public bool IsCancellationRequested { get; set; } = false;
+
+ BackgroundWorker contPingBackgroundWorker = new BackgroundWorker();
+
+ public void InitatePingRequest(IPAddress ipAddress)
+ {
+ _ipAddress = ipAddress;
+
+ contPingBackgroundWorker.DoWork += ContPingBackgroundWorkerDoWork;
+ contPingBackgroundWorker.RunWorkerAsync();
+ }
+
+ ///
+ /// Will continuously ping the input IP address every 5 seconds,
+ /// will stop if a cancellation request is made.
+ ///
+ ///
+ ///
+ private void ContPingBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
+ {
+
+ while (IsCancellationRequested == false)
+ {
+ Thread.Sleep(5000);
+
+ Ping pingSender = new Ping();
+ IPAddress address = _ipAddress;
+ PingReply reply = pingSender.Send(address);
+
+ if (reply.Status == IPStatus.Success)
+ Debug.WriteLine("Ping Success!");
+ else
+ {
+ Debug.WriteLine(reply.Status);
+ }
+ }
+ }
+ }
+}
diff --git a/TimedShutdown/Properties/AssemblyInfo.cs b/TimedShutdown/Properties/AssemblyInfo.cs
index 737b87e..4eb03ae 100644
--- a/TimedShutdown/Properties/AssemblyInfo.cs
+++ b/TimedShutdown/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.1.0.0")]
+[assembly: AssemblyFileVersion("1.1.0.0")]
diff --git a/TimedShutdown/ShutdownManager.cs b/TimedShutdown/ShutdownManager.cs
index 6915e61..6479900 100644
--- a/TimedShutdown/ShutdownManager.cs
+++ b/TimedShutdown/ShutdownManager.cs
@@ -1,10 +1,15 @@
using System;
using System.Diagnostics;
+using System.Net.Sockets;
namespace TimedShutdown
{
public class ShutdownManager
{
+ private readonly Func _funcForceShutdown = ForceShutdown;
+ private readonly Func _funcShutdownOperation = ShutdownOperation;
+ private readonly Func _funcRemoteShutdown = RemoteShutdown;
+
public enum Operation
{
Shutdown,
@@ -17,18 +22,16 @@ namespace TimedShutdown
///
///
///
- public void ExecuteOperation(Operation shutdownoperation, int shutdownSeconds, bool forceShutdownState)
+ public void ExecuteOperation(Operation shutdownoperation, int shutdownSeconds, bool forceShutdownState, string remoteShutdown)
{
- Func forceShutdown = ForceShutdown;
- Func shutdownOperation = ShutdownOperation;
-
ProcessStartInfo info = new ProcessStartInfo();
Process proc = new Process();
info.FileName = "cmd.exe";
- info.Arguments = $"/c shutdown {ShutdownOperation(shutdownoperation)} -t" +
+ info.Arguments = $"/c shutdown {_funcShutdownOperation(shutdownoperation)} -t" +
$" {shutdownSeconds}" +
- $" {ForceShutdown(forceShutdownState)}";
+ $" {_funcForceShutdown(forceShutdownState)}" +
+ $" {_funcRemoteShutdown(remoteShutdown)}";
info.WindowStyle = ProcessWindowStyle.Hidden;
info.CreateNoWindow = true;
@@ -36,22 +39,23 @@ namespace TimedShutdown
proc.Start();
}
- public void AbortOperation()
+ public void AbortOperation(string remoteShutdown)
{
ProcessStartInfo info = new ProcessStartInfo();
Process proc = new Process();
info.FileName = "cmd.exe";
- info.Arguments = $"/c shutdown -a";
+ info.Arguments = $"/c shutdown -a {_funcRemoteShutdown(remoteShutdown)}";
info.CreateNoWindow = true;
info.WindowStyle = ProcessWindowStyle.Hidden;
+
proc.StartInfo = info;
proc.Start();
}
#region Functions
- private string ShutdownOperation(Operation arg)
+ private static string ShutdownOperation(Operation arg)
{
switch (arg)
{
@@ -64,11 +68,21 @@ namespace TimedShutdown
}
}
- private string ForceShutdown(bool arg)
+ private static string ForceShutdown(bool arg)
{
return "-f";
}
+ private static string RemoteShutdown(string arg)
+ {
+ if (string.IsNullOrEmpty(arg)) return string.Empty;
+ if (arg.StartsWith(@"\\"))
+ {
+ return $"-m {arg}";
+ }
+ return $@"-m \\{arg}";
+ }
+
#endregion
}
diff --git a/TimedShutdown/TimedShutdown.csproj b/TimedShutdown/TimedShutdown.csproj
index cf4470d..51bf3d1 100644
--- a/TimedShutdown/TimedShutdown.csproj
+++ b/TimedShutdown/TimedShutdown.csproj
@@ -70,6 +70,8 @@
MSBuild:Compile
Designer
+
+
diff --git a/TimedShutdown/ViewModels/ShellRootViewModel.cs b/TimedShutdown/ViewModels/ShellRootViewModel.cs
index 4f52710..1d5a775 100644
--- a/TimedShutdown/ViewModels/ShellRootViewModel.cs
+++ b/TimedShutdown/ViewModels/ShellRootViewModel.cs
@@ -1,4 +1,6 @@
using System;
+using System.Diagnostics;
+using System.Net;
using System.Windows.Media.Imaging;
using Caliburn.Micro;
@@ -6,29 +8,8 @@ namespace TimedShutdown.ViewModels
{
public class ShellRootViewModel : Screen
{
- readonly ShutdownManager shutdownManager = new ShutdownManager();
-
- #region Labels
-
- public string LabelWindowTitle { get; } = "Timed Shutdown";
-
- public string LabelHoursLabel { get; } = "Hours:";
-
- public string LabelMinutesLabel { get; } = "Minutes:";
-
- public string LabelShutdownOptions { get; } = "Options:";
-
- public string LabelShutdownOptionsForce { get; } = "Force Operation";
-
- public string LabelShutdownTime { get; set; } = "Shutdown Time:";
-
- public string LabelShutdown { get; } = "Shutdown";
-
- public string LabelReboot { get; } = "Reboot";
-
- public string LabelAbortShutdown { get; } = "Abort Shutdown";
-
- #endregion
+ private readonly ShutdownManager _shutdownManager = new ShutdownManager();
+ private readonly PingWidget pingWidget = new PingWidget();
#region Values
@@ -82,6 +63,66 @@ namespace TimedShutdown.ViewModels
public bool ShutdownOptionsForce { get; set; }
+ private string _remoteShutdown;
+ public string RemoteShutdown
+ {
+ get { return _remoteShutdown; }
+ set
+ {
+ // Show remote shutdown alert upon checking for a non-loopback
+ // address.
+ if (!string.IsNullOrEmpty(value)
+ && value != "localhost"
+ && value != "127.0.0.1")
+ {
+ Messaging alert = new Messaging();
+ alert.Show(Messaging.Message.RemoteShutdown, value);
+ }
+ _remoteShutdown = value;
+ }
+ }
+
+ private bool _pingRemoteHost;
+ public bool PingRemoteHost
+ {
+ get { return _pingRemoteHost; }
+ set
+ {
+ _pingRemoteHost = value;
+
+ if (value == true)
+ {
+ pingWidget.IsCancellationRequested = false;
+ pingWidget.InitatePingRequest(IPAddress.Parse(RemoteShutdown));
+ }
+ else
+ {
+ pingWidget.IsCancellationRequested = true;
+ }
+ }
+ }
+
+ public string PingRemoteHostStatus { get; set; }
+
+ #region Remote Expander
+
+ public int WindowHeight { get; set; } = 335; // Default 335
+
+ private bool _remoteExpander;
+ public bool RemoteExpander
+ {
+ get { return _remoteExpander; }
+ set
+ {
+ WindowHeight = value ? 460 : 335;
+ NotifyOfPropertyChange(() => WindowHeight);
+
+ _remoteExpander = value;
+ }
+ }
+
+ #endregion
+
#endregion
#region Buttons
@@ -89,44 +130,48 @@ namespace TimedShutdown.ViewModels
public bool CanShutdown { get; set; } = true;
public void Shutdown()
{
- shutdownManager.ExecuteOperation(ShutdownManager.Operation.Shutdown, ShutdownTime, false);
- CanAbortShutdown = true;
- CanReboot = false;
- CanShutdown = false;
+ _shutdownManager.ExecuteOperation(
+ ShutdownManager.Operation.Shutdown,
+ ShutdownTime,
+ ShutdownOptionsForce,
+ RemoteShutdown);
- NotifyOfPropertyChange(() => CanAbortShutdown);
- NotifyOfPropertyChange(() => CanReboot);
- NotifyOfPropertyChange(() => CanShutdown);
+ CanReboot = false;
+ CanShutdown = false;
+
+ NotifyOfPropertyChange(() => CanReboot);
+ NotifyOfPropertyChange(() => CanShutdown);
}
public bool CanReboot { get; set; } = true;
public void Reboot()
{
- shutdownManager.ExecuteOperation(ShutdownManager.Operation.Reboot, ShutdownTime, false);
- CanAbortShutdown = true;
- CanReboot = false;
- CanShutdown = false;
+ _shutdownManager.ExecuteOperation(
+ ShutdownManager.Operation.Reboot,
+ ShutdownTime,
+ ShutdownOptionsForce,
+ RemoteShutdown);
- NotifyOfPropertyChange(() => CanAbortShutdown);
- NotifyOfPropertyChange(() => CanReboot);
- NotifyOfPropertyChange(() => CanShutdown);
+ CanReboot = false;
+ CanShutdown = false;
+
+ NotifyOfPropertyChange(() => CanReboot);
+ NotifyOfPropertyChange(() => CanShutdown);
}
- public bool CanAbortShutdown { get; set; } = true;
public void AbortShutdown()
{
// Reset values to defaults.
Minutes = 0;
Hours = 0;
- shutdownManager.AbortOperation();
- CanAbortShutdown = false;
+ _shutdownManager.AbortOperation(RemoteShutdown);
CanReboot = true;
CanShutdown = true;
- NotifyOfPropertyChange(() => CanAbortShutdown);
NotifyOfPropertyChange(() => CanReboot);
NotifyOfPropertyChange(() => CanShutdown);
+ NotifyOfPropertyChange(() => RemoteShutdown);
}
#endregion
diff --git a/TimedShutdown/Views/ShellRootView.xaml b/TimedShutdown/Views/ShellRootView.xaml
index 99a0d5c..8dad97e 100644
--- a/TimedShutdown/Views/ShellRootView.xaml
+++ b/TimedShutdown/Views/ShellRootView.xaml
@@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
- Title="{Binding LabelWindowTitle}" Height="300" Width="400" WindowStartupLocation="CenterScreen"
+ Title="Timed Shutdown" Height="{Binding WindowHeight, Mode=TwoWay}" Width="400" WindowStartupLocation="CenterScreen"
ResizeMode="NoResize">
@@ -21,36 +21,37 @@
+
+ Margin="0,0,5,0" Grid.RowSpan="5" RenderOptions.BitmapScalingMode="Fant"/>
-
+
-
+
-
-
+
+
-
+
-
+
@@ -64,15 +65,50 @@
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TimedShutdown/bin/Release/TimedShutdown.exe b/TimedShutdown/bin/Release/TimedShutdown.exe
index 1f1e8a2..3240f7d 100644
Binary files a/TimedShutdown/bin/Release/TimedShutdown.exe and b/TimedShutdown/bin/Release/TimedShutdown.exe differ
diff --git a/TimedShutdown/bin/Release/TimedShutdown.pdb b/TimedShutdown/bin/Release/TimedShutdown.pdb
index eca23db..72933cc 100644
Binary files a/TimedShutdown/bin/Release/TimedShutdown.pdb and b/TimedShutdown/bin/Release/TimedShutdown.pdb differ