using Gma.System.MouseKeyHook;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.ServiceProcess;
using System.Timers;
using System.Windows.Forms;
namespace Sleepy
{
partial class Service : ServiceBase
{
private const long MOVEMENT_SPAN = TimeSpan.TicksPerSecond;
private const int MOVEMENT_DISTANCE = 50;
private bool locked = false;
private System.Timers.Timer timer;
private bool hooked = false;
private IKeyboardMouseEvents kmHooks = Hook.GlobalEvents();
private Tuple<DateTime, Point> mouseLocation;
private Config config;
public Service(Config config)
{
this.config = config;
timer = new System.Timers.Timer(config.Timeout * 1000);
timer.Elapsed += suspend;
CanHandlePowerEvent = true;
CanHandleSessionChangeEvent = true;
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
stop();
}
protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
{
switch (powerStatus)
{
case PowerBroadcastStatus.Suspend:
Console.WriteLine("Workstation has been suspended.");
stop();
break;
case PowerBroadcastStatus.ResumeAutomatic:
case PowerBroadcastStatus.ResumeCritical:
case PowerBroadcastStatus.ResumeSuspend:
Console.WriteLine("Workstation has been resumed.");
start();
break;
}
return true;
}
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
switch (changeDescription.Reason)
{
case SessionChangeReason.SessionLock:
Console.WriteLine("Workstation has been locked.");
locked = true;
break;
case SessionChangeReason.SessionUnlock:
case SessionChangeReason.SessionLogon:
Console.WriteLine("Workstation has been unlocked.");
locked = false;
stop();
break;
}
}
private void suspend(object sender, ElapsedEventArgs e)
{
if (config.WindowsUpdate && isWindowsUpdateRunning())
{
Console.WriteLine("Windows Update is seems to be running.");
start();
return;
}
Console.WriteLine("Timer elapsed, returning to sleep.");
stop();
Application.SetSuspendState(PowerState.Suspend, true, true);
}
private void hook()
{
if (hooked)
{
return;
}
kmHooks.KeyPress += onKeyPress;
kmHooks.MouseMove += onMouseMove;
kmHooks.MouseClick += onMouseClick;
mouseLocation = null;
}
private void unhook()
{
if (!hooked)
{
return;
}
kmHooks.KeyPress -= onKeyPress;
kmHooks.MouseMove -= onMouseMove;
kmHooks.MouseClick -= onMouseClick;
mouseLocation = null;
}
private void onKeyPress(object sender, KeyPressEventArgs e)
{
onActivity();
}
private void onMouseMove(object sender, MouseEventArgs e)
{
if (mouseLocation == null)
{
mouseLocation = new Tuple<DateTime, Point>(DateTime.Now, e.Location);
}
else if (DateTime.Now.Ticks > mouseLocation.Item1.Ticks + MOVEMENT_SPAN)
{
var distance
= (e.Location.X - mouseLocation.Item2.X) * (e.Location.X - mouseLocation.Item2.X)
+ (e.Location.Y - mouseLocation.Item2.Y) * (e.Location.Y - mouseLocation.Item2.Y);
mouseLocation = new Tuple<DateTime, Point>(DateTime.Now, e.Location);
if (distance > MOVEMENT_DISTANCE * MOVEMENT_DISTANCE)
{
onActivity();
}
}
}
private void onMouseClick(object sender, MouseEventArgs e)
{
onActivity();
}
private void onActivity()
{
if (timer.Enabled && !locked)
{
Console.WriteLine("An activity detected on unlocked workstation.");
stop();
}
}
private void start()
{
Console.WriteLine(timer.Enabled ? "Restarting the timer." : "Starting the timer.");
hook();
mouseLocation = null;
timer.Stop();
timer.Start();
}
private void stop()
{
if (timer.Enabled)
{
Console.WriteLine("Stopping the timer.");
}
mouseLocation = null;
timer.Stop();
unhook();
}
static private bool isWindowsUpdateRunning()
{
foreach (var process in Process.GetProcesses())
{
try {
var file = Path.GetFileName(process.MainModule.FileName).ToLower();
if (file == "msiexec.exe" || file == "trustedinstaller.exe")
{
return true;
}
} catch {
}
}
return false;
}
}
}