WPF: application Idle Time - c#

I need to count the idle time of my WPF application (Idle time = when no keyboard input,mouse input (movement + clicks ) had occurred ).
So far I tried 2 approaches but none of them seem to be working:
Using the dispatcher to invoke a delegate each time it get a contextIdle priority, the problem is that binding and many other operations invoke it and thus I can't really use that.
using the input manager I registered to the "System.Windows.Input.InputManager.Current.PostProcessInput" event and each time it was invoked I restarted the idle time count.
The second approach seemed promising but the problem is that when the mouse is over the application (it has focus) I keep getting the event.
Any Other ideas? or maybe a way to modify the 2nd solution to work?

I solved the problem using a few different techniques rolled up to give me a pretty good solution. I use GetLastInput to work out when the system was last touched This is well documented elsewhere, but here's my method:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
}
This only tells me when the system has been idle, not the application. If the user clicks into Word and works there for an hour, I still want a timeout. To handle this case, I simply remember when my application loses focus by overriding the OnDeactivated and OnActivated methods on the application object:
override protected void OnDeactivated(EventArgs e)
{
this._lostFocusTime = DateTime.Now;
base.OnDeactivated(e);
}
protected override void OnActivated(EventArgs e)
{
this._lostFocusTime = null;
base.OnActivated(e);
}
My IsIdle routine was added to the application object. It handles the global case where the app has focus but nothing happened (IsMachineIdle) and the specific case where the application lost focus while the user is doing other stuff (isAppIdle ):
public bool IsIdle
{
get
{
TimeSpan activityThreshold = TimeSpan.FromMinutes(1);
TimeSpan machineIdle = Support.User32Interop.GetLastInput();
TimeSpan? appIdle = this._lostFocusTime == null ? null : (TimeSpan?)DateTime.Now.Subtract(_lostFocusTime.Value);
bool isMachineIdle = machineIdle > activityThreshold ;
bool isAppIdle = appIdle != null && appIdle > activityThreshold ;
return isMachineIdle || isAppIdle;
}
}
The last thing I did was create a timer loop that polled this flag event few seconds.
This seems to work fine.

Well no one seemed to answer so I continued digging and found a relatively simple solution using the OS last input + up time. the code is really simple but this solution make me do data polling which I never recommend and also instead of being in the application level it's in the OS level which is not the exact solution I needed.
If someone ever opens this thread this is the code, just use GetIdleTime():
public class IdleTimeService
{
//Importing the Dll & declaring the necessary function
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
/// <summary>
/// return the current idle time (in ms)
/// </summary>
/// <returns>current idle time in ms</returns>
public static int GetIdleTime()
{
//Creating the object of the structure
LASTINPUTINFO lastone = new LASTINPUTINFO();
//Initialising
lastone.cbSize = (uint)Marshal.SizeOf(lastone);
lastone.dwTime = 0;
int idleTime = 0;
//To get the total time after starting the system.
int tickCount = System.Environment.TickCount;
//Calling the dll function and getting the last input time.
if (GetLastInputInfo(ref lastone))
{
idleTime = tickCount - (int)lastone.dwTime;
return idleTime;
}
else
return 0;
}
}

Related

How to distinguish a physical mouse click from a code one?

I'm writing an autoclicker right now. I have a very difficult problem to solve at my level of knowledge.
I have low level hooks to detect Mouse KeyDown & KeyUp.
private bool LeftButtonStatus;
private void AutoClicker_Load(object sender, EventArgs e)
{
core.mouseHook.LeftButtonDown += new MouseHook.MouseHookCallback(mouseHook_LeftKeyDown);
core.mouseHook.LeftButtonUp += new MouseHook.MouseHookCallback(mouseHook_LeftKeyUp);
}
private void mouseHook_LeftKeyDown(MouseHook.MSLLHOOKSTRUCT ma)
{
LeftButtonStatus = true;
StartClicking();
}
private void mouseHook_LeftKeyUp(KeyboardHook.VKeys key)
{
LeftButtonStatus = false;
StartClicking();
}
private void StartClicking()
{
if (LeftButtonStatus)
LeftButtonTimer.Start();
else
LeftButtonTimer.Stop();
}
private void LeftButtonTimer_Tick(object sender, EventArgs e)
{
Core.LeftClick();
}
My click method in the Core class looks like this:
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
public static void LeftClick()
{
mouse_event(((int)KeyStates.LeftDown) | ((int)KeyStates.LeftDown), 0, 0, 0, 0);
}
The problem is that when I call Core.LeftClick(); my hooks detect it
and stops the Timer.
How to do I make sure Core.LeftClick(); is ignored by the mouseHook_LeftKeyUp and mouseHook_LeftKeyDown methods?
You could use a flag in your own code where you set ignore = true in LeftClick() and check if (ignore == true) in your hook methods. But the problem there is you open yourself up to a race condition where a user-generated click could be processed between the time that it's set to true and when your hook is run, which would lead to a user-generated click being ignored.
A better way would be to use the dwExtraInfo parameter of mouse_event. The documentation describes it as:
An additional value associated with the mouse event.
This seems like a great way to send some flag along in the event itself.
It is meant to be a pointer to a location in memory for some data, but I found an example of someone setting it to some arbitrary integer value (in their case 111) and it presumably worked. You could try that.
It would look something like this:
public static void LeftClick()
{
mouse_event(((int)KeyStates.LeftDown) | ((int)KeyStates.LeftDown), 0, 0, 0, 111);
}
private void mouseHook_LeftKeyDown(MouseHook.MSLLHOOKSTRUCT ma)
{
if (ma.dwExtraInfo == 111) return;
LeftButtonStatus = true;
StartClicking();
}
Your method signature for mouseHook_LeftKeyUp is different, but is that correct? If you can change that to use MSLLHOOKSTRUCT too, then you can do the same there, if you need to.
In your DllImport attribute, the type of dwExtraInfo should technically be IntPtr, but in this case it shouldn't matter.
This answer consolidates and incorporates info and ideas from other SO posts here and here.
Your question is how to distinguish a physical mouse click from a virtual one. I see that in your code you're using a mouse hook and one way to "close the loop" is by examining the dwExtraInfo flag in the callback per Gabriel Luci's excellent suggestion. But what I set out to do is find a threadsafe approach that doesn't rely on a hook to detect auto clicks so I ended up discarding the mouse hook for my testing. And I tried several things, but what I found was most reliable in my experience is to essentially set a ~100 ms watchdog timer using a thread synchronization object (like the easy-to-use SemaphoreSlim). This semaphore can be tested by whatever target ultimately consumes the click to determine whether the WDT is has expired by calling Wait(0) on the semaphore and looking at the bool return value.
In the first of two tests, I checked the AutoClick button and let it run. As expected, the physical click shows up in black and the auto clicks show up in blue. The indicators all light up as expected.
For the autoClick methods, I used SendInput since mouse_event is obsolete (see Hans Passant comment on this post.
public void autoClick(Control control)
{
autoClick(new Point
{
X = control.Location.X + control.Width / 2,
Y = control.Location.Y + control.Height / 2,
});
}
public void autoClick(Point clientPoint)
{
Cursor.Position = PointToScreen(clientPoint);
var inputMouseDown = new INPUT { Type = Win32Consts.INPUT_MOUSE };
inputMouseDown.Data.Mouse.Flags = (uint)MOUSEEVENTF.LEFTDOWN;
// Go ahead and decorate with a flag as Gabriel Luci suggests.
inputMouseDown.Data.Mouse.ExtraInfo = (IntPtr)MOUSEEXTRA.AutoClick;
var inputMouseUp = new INPUT { Type = Win32Consts.INPUT_MOUSE };
inputMouseUp.Data.Mouse.Flags = (uint)MOUSEEVENTF.LEFTUP;
var inputs = new INPUT[]
{
inputMouseDown,
inputMouseUp,
};
if (0 == SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT))))
{
Debug.Assert(false, "Error: SendInput has failed.");
}
}
[Flags]
enum MOUSEEXTRA : uint{ AutoClick = 0x40000000, }
The handler for the Auto Click 5 checkbox positions and clicks the mouse to light up 5 "indicator" check boxes.
const int SETTLE = 100;
SemaphoreSlim _sslimAutoClick = new SemaphoreSlim(1, 1);
/// <summary>
/// Responds to the button by auto-clicking 5 times.
/// </summary>
private async void onAutoClick(object sender, EventArgs e)
{
if (checkBoxAutoClick.Checked)
{
checkBoxAutoClick.Enabled = false;
foreach (var indicator in indicators)
{
await _sslimAutoClick.WaitAsync();
autoClick(indicator);
// Don't await here. It's for the benefit of clients.
Task
.Delay(SETTLE)
.GetAwaiter()
.OnCompleted(() =>_sslimAutoClick.Release());
// Interval between auto clicks.
await Task.Delay(TimeSpan.FromSeconds(2));
}
checkBoxAutoClick.Enabled = true;
checkBoxAutoClick.Checked = false;
}
}
As a more rigorous test, I repeated this but while the 5x autoclick is running I did a few manual clicks to make sure they intersperse and print in black. Again, it worked as expected.
If you'd like to browse the full code or experiment with it, the full sample code is on GitHub.

WPF Always on Top doesn't work [duplicate]

I have a clock application. I have set the Window's TopMost property. But, randomly, some other window or visual studio comes above clock.
Is there any other way to make my window (clock app) to display always on top of all other applications.
I know that this question is old, but I don't quite understand why the accepted answer has received up votes... or why it was accepted... it doesn't really answer the question, or provide a solution and answers posted these days that are that short are almost always down voted and/or deleted by the community. Ah well, I guess it was posted in different times.
Either way, as old as it is, I have a possible solution for anyone who may come across this post in the future. You can simply handle the Window.Deactivated Event and/or the Application.Deactivated Event. The Window.Deactivated Event occurs when a window becomes a background window and the Application.Deactivated Event occurs when an application stops being the foreground application.
The idea is to set the relevant TopMost property to true each time your application or Window loses focus:
private void Window_Deactivated(object sender, EventArgs e)
{
// The Window was deactivated
this.TopMost = true;
}
It's worth noting that other developers can also use this technique, so this doesn't guarantee that your Window will always remain on top, but it works for me and the situation is still certainly improved by using it.
This should do the trick in most cases
private void Window_Deactivated(object sender, EventArgs e)
{
// The Window was deactivated
Topmost = false; // set topmost false first
Topmost = true; // then set topmost true again.
}
I also had this problem when setting Window.Topmost = true on already existing window sometimes worked, sometimes not. Below is my workaround, you can probably combine it with Window_Deactivated approach mentioned by other people, if WS_EX_TOPMOST style is lost at runtime.
App.Current.MainWindow.Topmost = true;
// Get this window's handle
IntPtr hwnd = new WindowInteropHelper(App.Current.MainWindow).Handle;
// Intentionally do not await the result
App.Current.Dispatcher.BeginInvoke(new Action(async () => await RetrySetTopMost(hwnd)));
Extra code:
private const int RetrySetTopMostDelay = 200;
private const int RetrySetTopMostMax = 20;
// The code below will retry several times before giving up. This always worked with one retry in my tests.
private static async Task RetrySetTopMost(IntPtr hwnd)
{
for (int i = 0; i < RetrySetTopMostMax; i++)
{
await Task.Delay(RetrySetTopMostDelay);
int winStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
if ((winStyle & WS_EX_TOPMOST) != 0)
{
break;
}
App.Current.MainWindow.Topmost = false;
App.Current.MainWindow.Topmost = true;
}
}
internal const int GWL_EXSTYLE = -20;
internal const int WS_EX_TOPMOST = 0x00000008;
[DllImport("user32.dll")]
internal static extern int GetWindowLong(IntPtr hwnd, int index);
Are you sure it's a random window? If another window is also a topmost window, it is possible for it to come above your window.

Increment a Temporary / Timed Variable in C#

Forgive the ignorance of this question, as I'm completely new to C#, but how would one go about setting and handling a temporary or timed variable? For example, whenever an event fires, I want to increment a counter. If the counter exceeds 3 within 60 seconds, I want to trigger another event. Elsewise, if 60 seconds passes and the counter isn't incremented, it resets back to 0.
Should I be using MemoryCache? Or is there some nifty flag I can set for variables to make them unset after a specified duration (assuming they aren't refreshed)? What would be the best way to go about accomplishing this simple task? Note that I'm not necessarily looking for someone to write it for me; just a helpful hand or suggestion to point me in the right direction. This is a rough outline of what I'm trying to accomplish:
private static int totalCount = 0;
private static double maxCount = 3;
private static double timeLimit = 60;
private static void TestEvent(object src, EventArgs mea)
{
totalCount++;
if (totalCount > maxCount)
{
DoSomething();
}
}
Thanks for any assistance you can offer. I make it a point to always reward helpful answers.
You could maintain a Queue<T> (see http://msdn.microsoft.com/en-us/library/7977ey2c.aspx), where each entry is the time that an event fired. When an event fires, you first remove from the queue any entries that are more than 60 seconds old (which is easy, because the queue is ordered by time, and the head of the queue is the oldest entry), then add a new entry for the event that just fired. If the count of the queue exceeds your threshold, then you have satisfied the condition you're looking for.
I recommend using DateTime.UtcNow instead of DateTime.Now for the time you store in the Queue<T>. UtcNow is much faster, and it avoids the problem that transitions from daylight savings time to standard time and vice versa can cause.
Here is some code off the top of my head (may need a little fixing up):
private static Queue<DateTime> eventQueue = new Queue<DateTime>();
private static int timeWindowSeconds = 60;
private static int threshold = 3;
private static void TestEvent(object src, EventArgs mea) {
DateTime now = DateTime.UtcNow;
DateTime tooOld = now.AddSeconds(-timeWindowSeconds);
// remove old entries
while((eventQueue.Count > 0) && (eventQueue.Peek() < tooOld)) {
eventQueue.Dequeue();
}
// add new entry
eventQueue.Enqueue(now);
// test for condition
if (eventQueue.Count >= threshold) {
eventQueue.Clear();
DoSomething();
}
}
You might do it like this:
private static int totalCount = 0;
private static double maxCount = 3;
private static TimeSpan timeLimit = TimeSpan.FromSeconds(60);
private static DateTime lastIncrementTime;
private static void TestEvent(object src, EventArgs mea)
{
// If the time between now and lastIncrementTime is more than the timeLimit...
if(DateTime.Now - lastIncrementTime > timeLimit)
{
totalCount = 0;
}
lastIncrementTime = DateTime.Now;
totalCount++;
if (totalCount > maxCount)
{
DoSomething();
}
}
You can use the StopWatch class.
On the form load event (if you want to count the 60 second from that event), start the timer,
Everytime in the click event,check how many seconds it is invoked your other method or so.
I'd do something like this:
private class SomeEventMonitor
{
public int Threshold { get ; private set ; }
public TimeSpan ThresholdWindow { get ; private set ; }
private DateTime marker ;
private int count ;
/// <summary>
/// public constructor
/// </summary>
/// <param name="threshold"></param>
/// <param name="window"></param>
public SomeEventMonitor( int threshold , TimeSpan window )
{
if ( threshold < 1 ) throw new ArgumentOutOfRangeException("threshold") ;
if ( window <= TimeSpan.Zero ) throw new ArgumentOutofRangeException("window") ;
this.Threshold = threshold ;
this.ThresholdWindow = window ;
Reset() ;
return ;
}
private void Reset()
{
this.marker = DateTime.Now ;
this.count = 0 ;
return ;
}
public event EventHandler ThresholdExceeded ;
private static readonly object latch = new object() ;
public void EventWatcher( object source , EventArgs eventArgs )
{
lock ( latch )
{
DateTime current = DateTime.Now ;
if ( ++count > Threshold )
{
TimeSpan window = current -marker ;
if ( window > ThresholdWindow )
{
ThresholdExceeded( this , new EventArgs() ) ;
Reset() ;
}
}
}
return ;
}
}
You can use another variable to log the time of changing the value of totalcount. check it with the current time and do whatever you want.
Here is the code...
private static int totalCount = 0;
private static double maxCount = 3;
private static double timeLimit = 60;
private static DateTime timeflag= DateTime.Now;
private static void TestEvent(object src, EventArgs mea)
{
if (timeflag.AddSeconds(timeLimit) < DateTime.Now)
{
totalCount = 0;
}
totalCount++;
timeflag = DateTime.Now;
if (totalCount > maxCount)
{
DoSomething();
}
}
There are myriad ways you could approach this. The first thing that comes to mind for me would be to use a Stopwatch object or a Timer object that starts on a background thread, and then write an event handler that can subscribe to the event in which you're interested. As the event occurs, your handler fires, allowing you to suspend the timer and query the time elapsed, and make your increment/reset decision accordingly.
That's merely a very rough sketch of one notion, but should give you some ideas moving forward. Good luck.
Per the comment made by #hatchet above, this almost starts to sound like a queue with "expiring" members or a "sliding window" event horizon you'd have to capture should that comment accurately reflect your problem.
EDIT Being the borderline obsessive-compulsive that I am, I gave your original problem some thought and came up with a concept that may or may not be relevant to your problem, but at least for the academic exercise I'm going to post what I did. What caught my attention in your original post was the notion of an expiring or timed variable which I thought was quite novel. Your problem specified that you want to do something specific when a given interval elapses.
I tried to abstract that idea into a generic form, thinking of a few ways such an idea might be useful. One idea that came to mind was in a game environment, where (for example) a message might only be available to the player for 20 seconds before "self-destructing." I could imagine how having the expiration "plumbing" wired into a type might prove very convenient. Another scenario could be in a CAI environment where a System.Drawing.Image should only be displayed for a fixed time, then disappear - again, a scenario where having the expiration and timing code built-in could be useful.
So, with at least that much notional practicality in mind, I set to work, and what I threw together (and I won't pretend that its comprehensive or complete) is a generic for an Expiring type, expressed as Expiring<T>. The baseline code I've put together is as follows:
// First stab at an "expiring" type that is only valid for a set interval.
public class Expiring<T>
{
public delegate void ExpiredHandler(object sender, EventArgs e);
public event ExpiredHandler OnExpired;
T instance;
int signaledCount = 0;
long milliseconds = 0;
bool isExpired = false;
bool exceptOnExpiredReference = true;
System.Timers.Timer lapseTimer = new System.Timers.Timer();
public Expiring(T value)
{
instance = value;
}
public virtual void TimerElapsed(object sender, System.Timers.ElapsedEventArgs args)
{
if (OnExpired != null)
{
OnExpired(this, null);
}
isExpired = true;
}
public Expiring(T startValue, long expirationInterval, bool throwElapsedReferenceException):this(startValue)
{
milliseconds = expirationInterval;
lapseTimer.AutoReset = true;
lapseTimer.Interval = milliseconds;
exceptOnExpiredReference = throwElapsedReferenceException;
lapseTimer.Elapsed+=new System.Timers.ElapsedEventHandler(TimerElapsed);
this.Set();
}
public void Set()
{
signaledCount++;
lapseTimer.Stop();
lapseTimer.Start();
}
public T Value
{
get
{
if (!isExpired || !exceptOnExpiredReference)
return instance;
else
throw new InvalidOperationException("Reference to an expired value.");
}
set
{
instance = value;
}
}
}
The idea here is that someone could declare an Expiring<int>, specify its initial value, expiration time, and a value to indicate whether an attempt to access the value of an instance after the expiration interval has passed should throw an exception. When the expirationInterval passes, the OnExpired event is raised, allowing the declarer to specify a custom event handler to provide custom actions when the value expires.
If the caller wishes to reset the expiration timer, he need only call the Set() method of the object. That also increments an internal "signaledCount" value that I ultimately did not use, but was thinking of in terms of determining how many times the expiration timer has been reset. If the Value property of the object is accessed after the expiration interval passes, an InvalidOperationException is thrown with a "Value has expired" message.
This idea, unfortunately, has more notional/academic value than practical, I'm afraid. It would have a great deal more utility if it were possible to overload all the arithmetic operators to the implementations of the native value types, but I discovered quickly that C# doesn't like this notion at all (and found that out right here on a rather extensive post on the subject here on SO). Ideally, I'd love to be able to say something like:
Expired<Int32> foo = new Expired<Int32>(5,10000,true);
Expired<Int32> bar = new Expired<Int32>(10,10000,true);
Expired<Int32> baz = foo+bar; // can't make that work
There was some notion that this problem could be overcome with dynamic types, but I opted not to pursue it at this point. The idea, as I hammered it out, is offered for discussion as it applies to a generic view of the OP's "timed variable" notion. Constructive comments/criticism/refinements encouraged and welcome.

Prevent Windows workstation (desktop) from locking while running a WPF program

Issue:
I have a WPF fullscreen application, which acts as a dashboard. The computer is in domain and domain policies enforce the computer to be locked in 10 minutes after the last user activity. I want to prevent the workstation (or desktop) from locking automatically.
An example of such behavior: Windows Media Player, which prevents this while a movie is running.
Known solutions (kinda workarounds):
It is possible to send a Win32 Mouse Move event every fixed interval of time (for example, every minute)
It is possible to send a key to the program (for example "Left Shift" key up) every fixed interval of time (for example, every minute)
QUESTION:
How can I prevent windows workstation from locking without using these workarounds?
Disclaimer:
I was pretty sure, there should be a similar question answered somewhere on StackOverflow, but i didn't find any. I would appreciate, if you could point me into the right direction.
The solution has been pointed out through the comments, but I'm providing a simple starter solution for anyone else arriving via a web search:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
public App()
{
InitializeComponent();
App.Current.Startup += new StartupEventHandler((sender, e) =>
{
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
});
App.Current.Exit += new ExitEventHandler((sender, e) =>
{
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
});
}
}
[FlagsAttribute]
public enum EXECUTION_STATE : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
An alternative place to put the logic would be within an event handler for StateChanged on your main application window:
this.StateChanged += new EventHandler((sender, e) =>
{
if (WindowState == System.Windows.WindowState.Maximized)
{
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
else
{
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
}
});

Wiggling the mouse

OK. This is a bit of a vanity app, but I had a situation today at work where I was in a training class and the machine was set to lock every 10 minutes. Well, if the trainers got excited about talking - as opposed to changing slides - the machine would lock up.
I'd like to write a teeny app that has nothing but a taskbar icon that does nothing but move the mouse by 1 pixel every 4 minutes.
I can do that in 3 ways with Delphi (my strong language) but I'm moving to C# for work and I'd like to know the path of least resistance there.
for C# 3.5
without notifyicon therefore you will need to terminate this application in task manager manually
using System;
using System.Drawing;
using System.Windows.Forms;
static class Program
{
static void Main()
{
Timer timer = new Timer();
// timer.Interval = 4 minutes
timer.Interval = (int)(TimeSpan.TicksPerMinute * 4 / TimeSpan.TicksPerMillisecond);
timer.Tick += (sender, args) => { Cursor.Position = new Point(Cursor.Position.X + 1, Cursor.Position.Y + 1); };
timer.Start();
Application.Run();
}
}
The "correct" way to do this is to respond to the WM_SYSCOMMAND message. In C# this looks something like this:
protected override void WndProc(ref Message m)
{
// Abort screensaver and monitor power-down
const int WM_SYSCOMMAND = 0x0112;
const int SC_MONITOR_POWER = 0xF170;
const int SC_SCREENSAVE = 0xF140;
int WParam = (m.WParam.ToInt32() & 0xFFF0);
if (m.Msg == WM_SYSCOMMAND &&
(WParam == SC_MONITOR_POWER || WParam == SC_SCREENSAVE)) return;
base.WndProc(ref m);
}
According to MSDN, if the screensaver password is enabled by policy on Vista or above, this won't work. Presumably programmatically moving the mouse is also ignored, though I have not tested this.
When I work from home, I do this by tying the mouse cord to a desktop fan which oscillates left to right. It keeps the mouse moving and keeps the workstation from going to sleep.
Something like this should work (though, you will want to change the interval).
public Form1()
{
InitializeComponent();
Timer Every4Minutes = new Timer();
Every4Minutes.Interval = 10;
Every4Minutes.Tick += new EventHandler(MoveNow);
Every4Minutes.Start();
}
void MoveNow(object sender, EventArgs e)
{
Cursor.Position = new Point(Cursor.Position.X - 1, Cursor.Position.Y - 1);
}
(Windows 10 / .Net 5 / C# 9.0)
Instead of faking activity, you could
inform the system that it is in use, thereby preventing the system
from entering sleep or turning off the display while the application
is running
using SetThreadExecutionState, as described on PInvoke.net :
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace VanityApp
{
internal static class Program
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);
[Flags]
private enum ExecutionState : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
}
private static void Main()
{
using AutoResetEvent autoResetEvent = new AutoResetEvent(false);
using Timer timer = new Timer(state => SetThreadExecutionState(ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_CONTINUOUS | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_SYSTEM_REQUIRED), autoResetEvent, 0, -1);
autoResetEvent.WaitOne();
}
}
}
The Timer is a System.Threading.Timer, with its handy constructor, and it uses AutoResetEvent.WaitOne() to avoid exiting immediately.
Raf provided a graceful answer to the problem for Win10 world, but unfortunately, his autoResetEvent.WaitOne() instruction blocks the thread, and therefore it must be in a separate thread of its own.
What worked for me can actually run in the main thread, the code doesn't have to be placed in the Main() method, and you can actually have a button to enable this functionality and one to disable it.
First, you certainly need to define the execution state flags:
[Flags]
private enum ExecutionState : uint // options to control monitor behavior
{
ES_AWAYMODE_REQUIRED = 0x00000040, // prevent idle-to-sleep
ES_CONTINUOUS = 0x80000000, // allow monitor power down
ES_DISPLAY_REQUIRED = 0x00000002, // prevent monitor power down
ES_SYSTEM_REQUIRED = 0x00000001 // keep system awake
}
Now, whenever you want to keep your system awake and block your monitor from turning off or idling to sleep, all you need to do, is execute a single command:
SetThreadExecutionState(ExecutionState.ES_AWAYMODE_REQUIRED | ExecutionState.ES_CONTINUOUS | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_SYSTEM_REQUIRED);
Then, if you want to undo this action and return your system back to its original execution state, just issue the following command:
SetThreadExecutionState(ExecutionState.ES_CONTINUOUS);
Keep in mind, each command will return the previous execution state, which means, when you first alter this state, you can cache the returned value locally and use it if/when you want to restore the previous state.

Categories