C# как долго пользователь был неактивен

некоторые предпосылки: Я пишу приложение с несколькими формами и т. д. Пользователи должны войти в систему, чтобы использовать большинство функций, и это работало нормально до сих пор. Однако теперь клиент запросил, чтобы пользователь вышел из системы через определенное количество неактивного времени. Проблема в том, что пользователь все еще может быть активен на компьютере, просто не в моем приложении. Чтобы быть ясным, я должен выйти из системы, когда он неактивен в моем приложении, даже если он все еще взаимодействует с рабочий стол.

сначала я думал, что это будет довольно простой. Просто запомните время последнего действия, сравните его постоянно в таймере с текущим временем и выйдите из системы, если прошедшее время больше допустимого. Однако я понял, что выяснить время последнего действия может быть не так просто...

конечно, я мог бы скопировать вставить что-то вроде

Program.LastActionTime = DateTime.Now;

в каждом onChange, после чего, на кнопке и т. д., событие ... Однако не только это было бы a большой объем работы из-за размера приложения ... Это также было бы очень плохой практикой, и я уверен, что это будет забыто хотя бы один раз, что делает все это ненадежным (и кажется сломанным, ошибка будет почти невозможно воспроизвести!)

Итак, есть ли лучший способ?

6 ответов


в вашей программе.CS файл, вы можете обрабатывать приложение.Idle событие и сбросить таймер там. См.:

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


один подход, который я использовал в прошлом, создайте MessageFilter в анкете и проверьте наличие определенных типов событий, указывающих на активность пользователя:

 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;
        }
  }

затем в методе Main () формы перед вызовом Run ():

Application.AddMessageFilter(new UserActivityFilter());

одно предостережение, добавление сложного фильтра сообщений или добавление нескольких отдельных фильтров может замедлить отзывчивость вашего приложения.


можно переопределить WndProc, update Program.LastActionTime на каждой соответствующей Keyboard/Mouse сообщение о событии.


подключите обработчик событий к событиям MouseMove и KeyPressed, а затем проверьте фокус внутри этого события?


в целом было бы лучше всего получить эту информацию из вашей логики приложения вместо raw-ввода пользователя, но я предполагаю, что у вас нет гибкой инфраструктуры (возможно, используя команда), которые могли бы предоставить эту информацию.

поэтому я предлагаю просто зарегистрировать обработчики с вашей основной формой - если вы получаете клики или ключевые события (enable форма.KeyPreview для этого), ваш пользователь активен, и вы можете сбросить время бездействия.


вы можете создать базовый класс, от которого наследуются все ваши оконные формы. В базовом классе вы проверяете и сбрасываете тайм-аут при каждом нажатии клавиши или щелчке.