Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically prevent Windows screensaver from starting

Is there a recommended way to prevent the Windows screensaver from starting? The closest thing I've found is this article, but what I would really like to do is just tell Windows that the computer isn't idle rather than fooling with the currently set screensaver values.

like image 751
Michael Kelley Avatar asked Jan 21 '09 01:01

Michael Kelley


People also ask

What prevents screensaver from starting?

The screensaver not activating could be caused by three different issues: (1) a program is specifically preventing the screensaver, (2) the mouse is preventing the screensaver because it is “moving” due to a hair on the optical sensor (or dirty ball) or being perched on the edge of a desk/pad/etc, or (3) a program or ...

How do I delay Windows screensaver?

1] Change Screensaver time via SettingsOpen Start menu, and type screen saver. You should see the Change Screen Saver option. Click on it. Here you can change screen saver type, preview, open settings, change wait time, and choose to display lock screen on resume.

How do I bypass the screensaver?

Expand Control Panel, and then click Display. In the right pane, double-click Password protect the screen saver. Select Disable on the Policy tab. This prevents users from setting passwords on screen savers for this computer or domain.

How do I stop my computer from locking when idle?

Click Start>Settings>System>Power and Sleep and on the right side panel, change the value to “Never” for Screen and Sleep. Hope the information is helpful.


2 Answers

For testing, I set the screensaver to 1 minute and required a password.

I tried capturing SC_SCREENSAVE and returning -1 in VB .Net. As commented, it works when there is no screensaver password but fails if the screensaver password is active. (I tried it in Windows XP). I also put this into a Timer's tick event, every 1000 milliseconds:

Static dir As Integer = 4 Cursor.Position = Cursor.Position + New Size(dir, dir) dir = -dir 

It doesn't work. The cursor jiggles back and forth and after 1 minute the screensaver flashes on for a short instance and then turns off. The screensaver turns on for only a moment, not long enough to require a password. But still, the flash is ugly.

Then I tried using user32.dll's SetCursorPos and GetCursorPos. You can look them up at pinvoke. Same result as above.

Then I peeked at the code of "JiggleMouse" mentioned elsewhere in this question. JiggleMouse uses SendInput. SendInput works! No flash of the screensaver. I put a call to SendInput inside of a Timer that triggers every 50 seconds (just less than the minimum screensaver timeout of 60 seconds). It's sufficient to move the mouse by a delta of 0,0, no real movement. That does work. The code to put in the Tick event:

Dim i(0) As INPUT i(0).dwType = INPUT.InputType.INPUT_MOUSE i(0).mkhi = New MOUSEKEYBDHARDWAREINPUT i(0).mkhi.mi = New MOUSEINPUT i(0).mkhi.mi.dx = 0 i(0).mkhi.mi.dy = 0 i(0).mkhi.mi.mouseData = 0 i(0).mkhi.mi.dwFlags = MOUSEINPUT.MouseEventFlags.MOUSEEVENTF_MOVE i(0).mkhi.mi.time = 0 i(0).mkhi.mi.dwExtraInfo = IntPtr.Zero SendInput(1, i(0), Marshal.SizeOf(i(0))) 

This comes from pinvoke.com:

Public Declare Function SendInput Lib "user32" (ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer  Public Structure INPUT     Enum InputType As Integer         INPUT_MOUSE = 0         INPUT_KEYBOARD = 1         INPUT_HARDWARE = 2     End Enum      Dim dwType As InputType     Dim mkhi As MOUSEKEYBDHARDWAREINPUT End Structure  Public Structure MOUSEINPUT     Enum MouseEventFlags As Integer         MOUSEEVENTF_MOVE = &H1         MOUSEEVENTF_LEFTDOWN = &H2         MOUSEEVENTF_LEFTUP = &H4         MOUSEEVENTF_RIGHTDOWN = &H8         MOUSEEVENTF_RIGHTUP = &H10         MOUSEEVENTF_MIDDLEDOWN = &H20         MOUSEEVENTF_MIDDLEUP = &H40         MOUSEEVENTF_XDOWN = &H80         MOUSEEVENTF_XUP = &H100         MOUSEEVENTF_WHEEL = &H800         MOUSEEVENTF_VIRTUALDESK = &H4000         MOUSEEVENTF_ABSOLUTE = &H8000     End Enum      Dim dx As Integer     Dim dy As Integer     Dim mouseData As Integer     Dim dwFlags As MouseEventFlags     Dim time As Integer     Dim dwExtraInfo As IntPtr End Structure  Public Structure KEYBDINPUT     Public wVk As Short     Public wScan As Short     Public dwFlags As Integer     Public time As Integer     Public dwExtraInfo As IntPtr End Structure  Public Structure HARDWAREINPUT     Public uMsg As Integer     Public wParamL As Short     Public wParamH As Short End Structure  Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1 Const KEYEVENTF_KEYUP As UInt32 = &H2 Const KEYEVENTF_UNICODE As UInt32 = &H4 Const KEYEVENTF_SCANCODE As UInt32 = &H8 Const XBUTTON1 As UInt32 = &H1 Const XBUTTON2 As UInt32 = &H2  <StructLayout(LayoutKind.Explicit)> Public Structure MOUSEKEYBDHARDWAREINPUT     <FieldOffset(0)> Public mi As MOUSEINPUT     <FieldOffset(0)> Public ki As KEYBDINPUT     <FieldOffset(0)> Public hi As HARDWAREINPUT End Structure 
like image 117
Eyal Avatar answered Sep 19 '22 19:09

Eyal


Subtle. The official way to tell Windows that the system is not idle is SetThreadExecutionState. This resets the idle timer, (or turns it off, if you pass ES_CONTINUOUS ). However, even though SetThreadExecutionState resets the idle timer, it does not stop the screensaver!

like image 39
MSalters Avatar answered Sep 19 '22 19:09

MSalters