About me

Paolo Crippa, consulente informatico che opera come Project Leader e Technical Leader nella provincia di Milano, Lecco e Bergamo.
Grazie ad un solido background di base e oltre 20 anni d’esperienza con formazione continua sul campo , ho acquisito tecniche di progettazione flessibile,dinamica e mirata, che garantiscono risultati concreti in tempi brevi e grande soddisfazione del cliente.
Garantisco determinazione, propensione per il lavoro in team, attitudine allo studio analitico dei problemi ed ottime capacità organizzative.


0 Comments

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.

0 Comments

Visual Basic 6

Spesso capita di dover manutenere e implementare nuove funzionalità di progetti scritti in Visual Basic 6. Non avendo la possibilità di migrare queste applicazioni verso tecnologie più recenti ho cercato almeno di supportare questi progetti di tool esterni più recenti e produttivi.

Visual Studio 2019

Visual Studio 2019 permette in tutte le sue edizioni di integrare i progetti con un sistema molto potente di controllo di versione del sorgente che si integra localmente con GIT e centralmente con Azure DevOps o GitHub.

GIT

Non è necessario avere un progetto in Vusal Studio 2019 per  creare un repository di una cartella di progetto. Sono sufficienti una shell GIT  e una buona conoscenza delle istruzioni GIT. Non solo ma per ora è sufficiente.

Integrare una soluzione Visual Basic 6 in Azure DevOps

Sincronizzazione

Io l’ambiente di sviluppo Visual Basic 6 l’ho installato su una macchina virtuale Seven 32bit e sulla mia macchina fisica ho installato Visual Studio 2019. Questa situazione credo sia molto comune in quanto Visual Basic 6 non lo possiamo più installare sui recenti PC con Windows 10 a  64 bit

Il primo passaggio da fare è quello di creare una sincronizzazione del codice scritto sulla macchina virtuale in una cartella della macchina fisica e viceversa.

Per questa sincronizzazione sfrutto onedrive installato con lo stesso account  di accesso sia sulla macchina fisica che su quella virtuale e con una struttura di condivisione del tipo

Cartella onedrive macchina fisica

c:\onedrive\src\VB6

Cartella onedrive macchina virtuale

e:\onedrive\src\VB6


Questo mi assicura non solo una continua sincronizzazione del codice tra macchina virtuale e macchina fisica ma anche un backup continuo su onedrive.

Inizializzazione del repository

Apro Git Bash e mi porto sulla cartella della soluzione che voglio inizializzare come repostory.

$ cd /onedrive/src/VB6/ClientOrderEntru

Quindi inizializzo il repository

$ git init

 

A questo punto copio nella cartella un file .gitattributecosi fatto

# Set the default behavior, in case people don't have core.autocrlf set.

* text eol=auto

*.bas text eol=crlf

*.frm text eol=crlf

*.log text eol=crlf

*.vbp text eol=crlf

*.cls text eol=crlf

*.vbw text eol=crlf

*.dsr text eol=crlf

*.ini text eol=crlf

*.res binary

*.RES binary

*.frx binary

*.ctx binary

*.pgx binary

*.exe binary

*.dll binary

*.ico binary

*.gif binary

*.ocx binary

*.tlb binary

*.ocx.bin binary

*.ism binary

*.bin binary

*.aps binary

*.ncb binary

*.exe.compat binary

*.ocx.compat binary

E un file .gitignore cosi fatto:

.DS_Store

.Trashes

*.vbw

*.csi

*.exp

*.lib

*.lvw

*.dca

*.scc

*.tmp


A questo punto faccio il primo commit del repository

$ git commit -am “initial commit"

Open folder project in Visual Studio 2019


A questo punto è tutto pronto per vedere il risultato di questa integrazione Visual Basic -onedrive -GIT -Visual Studio 2019 -Azure Dev Ops

Prima di vedere il risultao entro nella macchina virtuale per fare qualche modifica della soluzione Visual Basic 6.

Passo sulla macchina fisica e apro Visual Studio 2019 , menu File>Open>Folder e scelgo la cartella C:\onedrive\src\VB6\ClientOrderEntry, che nel frattempo si è sincronizzata con le modifiche fatte nella macchina virtuale. (in questo passaggio prendetevi un caffe oppure mandate via 2 mail per prendere tempo o altro)

Il primo risultato che possiamo vedere in Visual Studio 2019 è lo stato delle modifiche fatte.


status change


Quindi possiamo verificare le differenze


differenze change


Comodo!Visual Basic 6 integrato con le funzioni di GIT e Azure DevOps di Visual Studio 2019.