2

I have a desktop application in which I would like to know two things:

  1. Is the user currently on the PC (more specifically, is he giving any input to the PC), so I can change his state to "away" if needed; and
  2. Is the screensaver running right now, so I can perform more CPU intensive work during that time.

I'm using C#/.NET. How would you suggest to tackle these two tasks?

NOTE: WIN32 invocation will be just as good, as well as any unmanaged code solution.

Eldad Mor
  • 5,405
  • 3
  • 34
  • 46

4 Answers4

5

http://dataerror.blogspot.com/2005/02/detect-windows-idle-time.html

^ Detect Windows Idle Time. :)

The enabler for this feature is the GetLastInputInfo() Win32 API and the LASTINPUTINFO Win32 structure.

Dennis C
  • 24,511
  • 12
  • 71
  • 99
Phill
  • 18,398
  • 7
  • 62
  • 102
  • 1
    Links are not answers -- well, not any more, at least. Answers on SO are expected to be self-contained. Please [review this meta question](http://meta.stackexchange.com/q/8231/135887) and add enough detail to your answer to make it not completely reliant on an external link. Perhaps a code sample? (This answer was flagged as Not an Answer.) – Charles Jan 28 '14 at 05:24
  • 2
    @Charles - I know, but I wrote this back in 2010. I think I had just joined SO at the time and no one had pointed me to "links are not answers" info. :) – Phill Jan 28 '14 at 06:50
  • True, and back then the standards weren't as strict... however, this answer was still flagged, and improving it would probably be a good idea. – Charles Jan 28 '14 at 07:16
  • @Charles - I concur, but can't update it while I'm at work. Need to read the link and question so will update the answer tonight. Good idea anyway incase the link dies the content will still be available. :) – Phill Jan 28 '14 at 07:20
5

Here is the code to detect if a screen saver is running. See this for more details

const int SPI_GETSCREENSAVERRUNNING = 114;

[DllImport( "user32.dll", CharSet = CharSet.Auto )]
private static extern bool SystemParametersInfo( 
   int uAction, int uParam, ref bool lpvParam, 
   int flags );


// Returns TRUE if the screen saver is actually running
public static bool GetScreenSaverRunning( )
{
   bool isRunning = false;

   SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, 
      ref isRunning, 0 );
   return isRunning;
}
Harvey Kwok
  • 11,713
  • 6
  • 37
  • 59
  • I thought this didn't work, but then I understood the reason: it doesn't work if you **preview** the screensaver! It has to be triggered automatically. So to test this, set your screensaver to 1 minute and wait. :) – Andrew Dec 29 '16 at 05:12
0

Rather than figuring out when to run more intensive work... Consider doing your "intensive work" as early as you can, but at a lower thread priority.

I don't think your questions have an answer in pure C#, unless you poll the mouse position and observe movements... Or something like that.

Arafangion
  • 11,517
  • 1
  • 40
  • 72
0

You could use a global keyboard/mouse hook and just reset your "counter" to 0 when you receive an event from either. When your counter reaches the idle time that you're looking for, perform your background actions.

There is some code here that allows you to easily do the hooking in .NET: http://www.codeproject.com/KB/cs/globalhook.aspx

Flipster
  • 4,373
  • 4
  • 28
  • 36
  • While this will work, using the [`GetLastInputInfo` function](http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_open_parameters.pdf) as suggested by Phill's answer is far easier than handling all of this yourself. – Cody Gray - on strike Dec 23 '10 at 06:23