39

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.

Fionnuala
  • 90,370
  • 7
  • 114
  • 152
Bruce the Hoon
  • 1,666
  • 3
  • 18
  • 21

6 Answers6

26

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();
    }
}
lubos hasko
  • 24,752
  • 10
  • 56
  • 61
  • Would this actually work? From memory, the "timeout" for kicking in of the screen saver is done somewhere in the O/S to do with input. Moving the mouse-position doesn't take the same logical path, so the user hasn't actually reset the countdown! – Ray Hayes Sep 20 '08 at 17:51
  • Lubos - I like it! I am going to modify it to alternate between moves so that after a day, the cursor will not be buried at the corner of the screen, but that's being picky - perhaps they would even like it that way. :) Thanks a lot for the fast, great answer! – Bruce the Hoon Aug 05 '08 at 04:44
12

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.

Zooba
  • 11,221
  • 3
  • 37
  • 40
10

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.

yoozer8
  • 7,361
  • 7
  • 58
  • 93
Heywoody
  • 101
  • 1
  • 2
3

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);
}
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
DylanJ
  • 2,373
  • 3
  • 25
  • 24
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.

1

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.

Mike O.
  • 61
  • 6