Session Timeout per Windows App
- Posted in:
- Visual Basic 6
Problema
Scrivo questo articolo in quanto mi è stato chiesto di gestire per un’applicazione windows un blocco della stessa se l’utente non la stà usando da 15 minuti. Praticamente una gestione di Session timeout per un’applicazione windows.
Session Timeout
Per un’applicazione WEB la gestione di un timeout della sessione rappresenta l'evento che si verifica quando un utente non esegue alcuna azione su un sito Web durante un intervallo (definito dal server Web). L'evento, sul lato server, modifica lo stato della sessione utente in "non valido" (ovvero "non più utilizzato"). Tutto questo è gestito in modo trasparente per il developer.
Windows App
Per un’applicazione windows possiamo raggiungere lo scopo con un pò più di fatica senza dover per forza scrivere codice in tutti i punti dell’applicazione dove l’utente interagisce con essa (menu, textbox, listbox ecc ecc)
API Windows
L’idea è quella di sfruttare le API di windows che intercettano i messaggi inviati dall’utente attraverso tastiera e mouse e riconoscere che questi messaggi sono inviati alla mia applicazione.
Dopo un pò di ricerche e tentativi trovo che la SetWindowsHookExdella libreria user32 è quella che soddisfa i miei requisiti.
Implementazione
A questo punto implemento il tutto su un progetto di prova per non toccare ancora il mostro.
Nel progetto inserisco un formmain con una serie di menu (simulo l’applicativo)
inserisco 3 form richiamabili dal menu con oggetti di vario genere buttati dentro a caso con lo scopo di simulare operazioni dell’utente.
Inserisco un form di nome frmSetWindowsHookEx con la funzione di apparire in modalità modale solo quando è raggiunto il timeout.
Un modulo per la gestione api.
Nel form principale dell’applicazione inserisco queste righe di codice nel load:
frmSetWindowsHookEx.InizializzaLocked
Sempre form principale dell’applicazione inserisco queste righe di codice nel unload:
RemoveKeyboardHook
Nel form di nome frmSetWindowsHookEx inserisco questo codice.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Option Explicit Private activitydate As Date Public Sub resetTimer() 'richiamata da ogni attività dell’utente sull’applicazione activitydate = Now End Sub Private Sub cmdAbilita_Click() SetKeyboardHook End Sub Private Sub Command1_Click() 'avviso all’utente dell’inattività e che è negessario ri RemoveKeyboardHook 'al posto della end si può far apparire il form del login dell’applicazione se c’è End End Sub Public Sub InizializzaLocked() SetKeyboardHook activitydate = Now Timer1.Enabled = True End Sub Private Sub Timer1_Timer() If DateDiff("n", activitydate, Now()) >= MINLOCKED Then Label1.Caption = Label1.Caption & " " & MINLOCKED & " MINUTI" Me.Show vbModal End If End Sub |
e nel modulo della gestione dell’api.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | Option Explicit Global Const MINLOCKED = 1 Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" ( _ ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long _ ) As Long Private Type POINTAPI x As Long y As Long End Type Private Declare Function UnhookWindowsHookEx Lib "user32" ( _ ByVal hHook As Long _ ) As Long Private Declare Function CallNextHookEx Lib "user32" ( _ ByVal hHook As Long, _ ByVal nCode As Long, _ ByVal wParam As Long, _ lParam As Any _ ) As Long Public Const WH_KEYBOARD = 2 Public Const WH_MOUSE = 7 Private Const HC_ACTION = 0 Public Type KBDLLHOOKSTRUCT vkCode As Long scanCode As Long flags As Long time As Long dwExtraInfo As Long End Type Private Const WH_GETMESSAGE = 3 Private hHookKeyboard As Long Private hHookMouse As Long Public IsHooked As Boolean Public Sub SetKeyboardHook() If IsHooked Then Else hHookMouse = SetWindowsHookEx(WH_MOUSE, AddressOf LowLevelKeyboardProc, App.hInstance, App.ThreadID) hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, AddressOf LowLevelKeyboardProc, App.hInstance, App.ThreadID) IsHooked = True End If End Sub Public Sub RemoveKeyboardHook() If IsHooked Then UnhookWindowsHookEx hHookKeyboard UnhookWindowsHookEx hHookMouse IsHooked = False End If End Sub Public Function LowLevelKeyboardProc(ByVal uCode As Long, ByVal wParam As Long, lParam As KBDLLHOOKSTRUCT) As Long If uCode >= 0 Then Select Case uCode Case HC_ACTION frmSetWindowsHookEx.resetTimer End Select LowLevelKeyboardProc = CallNextHookEx(hHookMouse, uCode, wParam, lParam) Else LowLevelKeyboardProc = CallNextHookEx(hHookMouse, uCode, wParam, lParam) End If End Function |
Comodo! Non devo scrivere codice ripetitivo in numerosi punti dell’applicazione e non devo preoccuparmi di inserire codice per la gestione del timeout anche nelle nuove funzionalità che ci potranno essere nel futuro di questa applicazione.