C # Per quanto tempo l’utente è stato inattivo

Qualche retroscena: sto scrivendo un’applicazione con diversi moduli, ecc. Gli utenti devono effettuare il login per poter utilizzare la maggior parte delle funzionalità, e questo ha funzionato fino ad ora. Tuttavia, ora, il client ha richiesto che l’utente venga disconnesso dopo una certa quantità di tempo inattivo. Il problema è che l’utente può essere ancora attivo sul computer, ma non nella mia applicazione. Per essere chiari, devo disconnettere l’utente quando è inattivo nella mia applicazione, anche se sta ancora interagendo con il desktop.

Per prima cosa ho pensato che sarebbe stato abbastanza semplice. Basta ricordare l’ora dell’ultima azione, confrontarla continuamente in un timer con l’ora corrente e disconnettere l’utente se il tempo trascorso è maggiore del tempo consentito. Tuttavia mi sono reso conto che scoprire l’ultimo tempo di azione potrebbe non essere così semplice …

Ovviamente potrei copiare incolla qualcosa del genere

Program.LastActionTime = DateTime.Now; 

in ogni evento OnChange, OnClick, ecc. Tuttavia, non solo questo sarebbe un gran lavoro a causa delle dimensioni dell’applicazione … Sarebbe anche una pessima pratica e sono sicuro che sarebbe ho dimenticato almeno una volta, rendendo l’intera cosa inaffidabile (e sembra rotto, il bug sarebbe quasi imansible da riprodurre!)

Quindi, c’è un modo migliore?

    Nel tuo file Program.CS, puoi gestire l’evento Application.Idle e resettare il tuo timer lì. Vedere:

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

    Un approccio che ho usato in passato, creare un MessageFilter nel modulo di domanda e verificare determinati tipi di eventi che indicano l’attività dell’utente:

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

    Quindi, nel metodo Main () del modulo, PRIMA della chiamata a Run ():

     Application.AddMessageFilter(new UserActivityFilter()); 

    Un avvertimento, l’aggiunta di un filtro messaggi complesso o l’aggiunta di più filtri separati possono rallentare la reattività dell’applicazione.

    È ansible eseguire l’override di WndProc e aggiornare Program.LastActionTime su ciascun messaggio evento Keyboard/Mouse pertinente.

    Agganciare un gestore di eventi agli eventi MouseMove e KeyPressed, quindi verificare la messa a fuoco all’interno di quell’evento?

    In generale, sarebbe meglio ricavare queste informazioni dalla logica dell’applicazione anziché dall’input dell’utente grezzo, ma presumo che non abbia un’infrastruttura flessibile (magari utilizzando lo schema di comando ) che potrebbe fornire queste informazioni.

    Quindi ti suggerisco di registrare i gestori con il tuo modulo principale – se ricevi clic o eventi chiave (abilita Form.KeyPreview per questo), l’utente è attivo e puoi resettare il tempo di inattività.

    È ansible creare una class base da cui ereditano tutte le forms della finestra. Nella class base controlli e resetta il tuo timeout su ogni KeyPress o Click.