Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# For how long was user inactive

Some background: I am writing a application with several forms, etc. Users have to log in in order to use most of the features, and this worked fine until now. However, now, client has requested that the user would be logged out after a certain amount of inactive time. The problem is that the user can still be active on the computer, just not in my application,. To be clear, I have to log the user out when he is inactive in my application, even if he is still interacting with the desktop.

First I thought this would be fairly simple. Just remember the time of the last action, compare it continually in a timer with current time and log out the user if the time passed is greater than the allowed time. However I have realised that finding out the last action time may not be so simple...

Of course I could copy paste something like

Program.LastActionTime = DateTime.Now;

in every OnChange, OnClick, etc, event ... However not only that this would be a great amount of work because of the size of the application ... It would also be a very bad practice and I'm sure it would be forgot at least once, making the whole thing unreliable (And appear broken, the bug would be almost impossible to reproduce!)

So, is there a better way?

like image 445
David Božjak Avatar asked Sep 14 '09 12:09

David Božjak


Video Answer


3 Answers

One approach that I've used in the past, create a MessageFilter on your application form and check for certain types of events that indicate user activity:

 public class UserActivityFilter : IMessageFilter
 {
        // Define WinAPI window message values (see pinvoke.net)
        private int WM_LBUTTONDOWN = 0x0201;
        private int WM_MBUTTONDOWN = 0x0207;
        private int WM_RBUTTONDOWN = 0x0204;
        private int WM_MOUSEWHEEL = 0x020A;
        private int WM_MOUSEMOVE = 0x0200;
        private int WM_KEYDOWN = 0x0100;

        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
            {
                //User activity has occurred
                // Reset a flag / timer etc.
            }
            return false;
        }
  }

Then in the Main() method of the form, BEFORE the call to Run():

Application.AddMessageFilter(new UserActivityFilter());

One caveat, adding a complex message filter or adding multiple separate filters can slow down the responsiveness of your application.

like image 190
Ash Avatar answered Sep 20 '22 01:09

Ash


In your Program.CS file, you can handle the Application.Idle event and reset your timer there. See:

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.idle.aspx

like image 20
MusiGenesis Avatar answered Sep 21 '22 01:09

MusiGenesis


You can override WndProc, update Program.LastActionTime on each relevant Keyboard/Mouse event message.

like image 28
manji Avatar answered Sep 22 '22 01:09

manji