Solved

Detecting system idleness

Posted on 2006-07-21
12
444 Views
Last Modified: 2010-05-19
In C#, how do I do the following:

I need to popup a certain window and play a sound when some event occurs. And this should happen ONLY when the user is actively using the system. One idea is to listen for mouse or keyboard events and decide based on when it was last moved / pressed.  In this case, I might probably catch the cases where the user is logged on but not using the system at all (for example if the screensaver is running).  But I'll not be able to detect the case when the PC is locked by the user (the user might lock his windows account with ctrl-alt-del and still move his mouse...  in this case, hes not actually looking at his desktop so this is not the right time for my window to popup).

Can someone tell me the best way to check system idleness?
0
Comment
Question by:v_karthik
  • 6
  • 6
12 Comments
 
LVL 22

Accepted Solution

by:
cookre earned 500 total points
ID: 17158682
0
 
LVL 22

Expert Comment

by:cookre
ID: 17158696
I honestly don't recall if LastInputInfo() reflects fiddling while the desktop is locked.  If it does, this may help out:

// ///////////////////////////////////////////////////////
// /////////////////////////////////////////////////////// GetLogonDesktopState
// ////////////////////////////////////////////////////////////////////////////
void GetLogonDesktopState()
{
LogonDesktopState=0;

IntPtr DeskTopHandle=(IntPtr)null;
try {
    DeskTopHandle=OpenDesktop("Winlogon",0,true,(long)0x41); // 41=enum & read
    }
catch (Exception e)
      {
      PutMsg("WinLogon open excp <"+e.ToString()+">");
      return;
      }
if (DeskTopHandle==IntPtr.Zero)
   {
   PutMsg("Unable to open Winlogon ("+GetLastError().ToString()+")");
   return;
   }
EnumDesktopWindows(DeskTopHandle,new EnumWinProc(EnumLogonWindows),0);
CloseDesktop(DeskTopHandle);
return;
}

// ///////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////// EnumLogonWindows
// ////////////////////////////////////////////////////////////////////////////
bool EnumLogonWindows(int hwnd,int lParam)
{
windowHandle=(IntPtr)hwnd;

StringBuilder sb=new StringBuilder(1024);
GetWindowText((int)windowHandle,sb,sb.Capacity);
if (sb.Length>0)
   {
   if (sb.ToString()=="Windows Security") {LogonDesktopState=1; return false;}
   if (sb.ToString()=="Computer Locked")  {LogonDesktopState=2; return false;}
   if (sb.ToString()=="Unlock Computer")  {LogonDesktopState=3; return false;}
   }
return true;
}








//
// Unfortunately, the screensaver and computer locked screens frequently
// switch back and forth without user action, to wit, on an idle box, the
// screensaver starts, runs for a while and is then replaced with the
// computer locked screen, which is later replaced with the screen saver,
// ad nauseum.
//
// Now, since our main concern in the reboot event is user activity, we
// won't consider a change fron ss running to the locked screen (or the
// reverse) as a user caused change in state.

GetLogonDesktopState();
if (IsSSRunning()) SSState=1;
              else SSState=0;

// Presume effective state change
StateChg=true;

// Now see if there really wasn't one
if ((PrevLogonDesktopState==LogonDesktopState) && (PrevSSState==SSState))
   {
   StateChg=false;
   }
else
   {
   if (   (   PrevLogonDesktopState==0   // Computer Locked wasn't visible
           && LogonDesktopState==2       // but now it is
           && PrevSSState==1             // and the screensaver went from running
           && SSState==0)                // to not running
                                         // OR
       || (   PrevLogonDesktopState==2   // Computer Locked was visible
           && LogonDesktopState==0       // but now it isn't
           && PrevSSState==0             // an the screensaver went from not running
           && SSState==1))               // to runing
      {
      StateChg=false;                    // Then that's not a real change.
      }
   }

// Tally what we found out
if (LogonDesktopState!=PrevLogonDesktopState) PrevLogonDesktopState=LogonDesktopState;
if (SSState!=PrevSSState) PrevSSState=SSState;
if (StateChg) MostRecentLogonDesktopStateChg=System.DateTime.Now;


0
 
LVL 4

Author Comment

by:v_karthik
ID: 17158831
thanks .. i'll try this out... but im afraid i understand only part of it. especially i dont understand the last part (i assume thats what tells me how to trigger my function when the user is actively using the PC) ... would u be able to give me a snippet that shows a MessageBox when the user is using the system?
0
 
LVL 22

Expert Comment

by:cookre
ID: 17159031
Before worrying about the provided code, run a test first to see if LastInputInfo() shows input when the desktop is locked.  If it doesn't, then that's all you need.
0
 
LVL 4

Author Comment

by:v_karthik
ID: 17160712
OK. I'll test it and get back to u. Thanks.
0
 
LVL 4

Author Comment

by:v_karthik
ID: 17178197
I tested it, and it does seem to detect input even when the desktop is locked.. so I need some other way to do this. I got this from microsoft site
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shutdown/base/lockworkstation.asp

It says,
"There is no function you can call to determine whether the workstation is locked. To verify whether it is worth attempting to update your user interface, you can test whether or not your window is visible. This also has the advantage of identifying when the user cannot see your user interface because it is obscured by another window, minimized, or offscreen."

I tried this IsWindowVisible api call, but it doesnt seem to work well for me. It always returns true (visible) even if I minimize it, hide it under other windows or lock the desktop.

If I have some other alternative to check if window is visible, I can try coupling it with lastinputinfo.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 22

Expert Comment

by:cookre
ID: 17179172
First, make sure the screen saver isn't running:

bool IsSSRunning()
{
IntPtr SSDeskTopHandle=(IntPtr)null;
try {
    SSDeskTopHandle=OpenDesktop("Screen-Saver",0,true,(long)0x41); // 41=enum & read
    }
catch // (Exception e)
      {
      // Nope
      }
if (!(SSDeskTopHandle==(IntPtr)null))
   {
   CloseDesktop(SSDeskTopHandle);
   Yup
   }
Nope



If it's not, make sure the desktop isn't:
   * pending lock (they just hit CtrlAltDel)
   * locked
   * pending unlock (it was locked, but some input occured)

See getLogonDesktopState() above.

It opens the logon desktop then looks for any of three windows.  If none of the three is found, the user desktop isn't locked.
0
 
LVL 4

Author Comment

by:v_karthik
ID: 17179473
With whatever I understood, I tried this ... I ran a test appln that checks every second if the computer is unlocked or locked and prints the result. I started getting "unlocked" messages, which was fine. I locked the computer, waited for a few seconds and logged in back. There was no "locked" message, all I saw was "unlocked".
0
 
LVL 4

Author Comment

by:v_karthik
ID: 17180152
http://blogs.msdn.com/shawnfa/archive/2005/05/17/418891.aspx?CommentPosted=true#commentmessage

I've tested the above, works like charm.  

Now, if I combine this and lastinputinfo, can I be sure that I cover all the cases? That is, Lastinputtime returns value close to current time, and if the machine is not locked, can I assume that the user is using the machine? Can you think of any other case that I've overlooked?
0
 
LVL 22

Expert Comment

by:cookre
ID: 17180682
The only other thing I can think of are game controllers, MIDI devices, and non-standard input devices like touch screens and pens.  The non-standard input devices are likely on dedicated boxes you won't be running on, and you probably don't want to interrupt someone in the middle of using the first two.

And thank you for the link - I've several services I can clean up with that method.
0
 
LVL 4

Author Comment

by:v_karthik
ID: 17180983
Thanks, that shouldnt be a big problem for my app I guess.

No problem. I'm going to accept ur answer, but one slightly unrelated question. Using the link I gave above, and also adding a timer to periodically check lastinputinfo, I thought of implementing a usercontrol so that I can share it with others if it comes out fine.

I used the user control wizard and added the code. All this is fine. Now when I actually add the control to an application (a form), the control doesnt seem to have a distinguishing background. That is, if I drag drop the control on the form, it kinda merges with the form and it becomes hard for me to locate the control later. I was wondering how to make it appear like the timer control (which resides below the form when u drag drop it). Or atleast, even if it resides on the form, I want it to appear like an icon or something so that I don't have to click all over the form to find it.  Do u have any input on this? I know this isnt related to my original q and this may not be very important, but I don't want the control to look too amateurish.
0
 
LVL 22

Expert Comment

by:cookre
ID: 17181046
Alas, I've never written any controls - I'm just a writer of low level system utilities.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Purpose To explain how to place a textual stamp on a PDF document.  This is commonly referred to as an annotation, or possibly a watermark, but a watermark is generally different in that it is somewhat translucent.  Watermark’s may be text or graph…
This is an explanation of a simple data model to help parse a JSON feed
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now