Newsgroup: it.comp.lang.visual-basic
Titolo: Controllare le scritture





Salve! Ho il problema di dover tenere sotto controllo c:\ ( e sotto 
directory)!!! Vorrei che mi fosse notificata una scrittura appena essa viene 
eseguita e magari avere il nome e il percorso del file appena scritto, è 
possibile??? CIAO E GRAZIE 1000!!!!!!!! 



 notificata una scrittura appena essa viene eseguita e magari avere il nome e il percorso del file appena > scritto, è possibile???
La faccenda è relativamente complessa.
Principalmente perché VB non esattamente lo strumento
più adeguato allo scopo.
Ad ogni modo, ti descrivo la procedura.
Ci sono due funzioni del kernel che permettono di monitorare
le modifiche effettuate a file o directory.
    FindFirstChangeNotification() e
    FindNextChangeNotification()
La prima viene utilizzata per iniziare un'operazione di monitoraggio.
La seconda per proseguirla, al verificarsi del primo evento di
modifica notificato dal sistema.
Il prototipo di FindFirstChangeNotification() è il seguente:
Public Declare Function FindFirstChangeNotification Lib "kernel32" _
    Alias "FindFirstChangeNotificationA" _
    (ByVal lpPathName As String, _
     ByVal bWatchSubtree As Long, _
     ByVal dwNotifyFilter As Long) As Long
Il parametro lpPathName viene utilizzato per indicare alla funzione
il percorso della directory da monitorare.
bWatchSubtree è un valore booleano che permette di indicare se
sono sottoposte a notifica le modifiche che si applicano all'intero
tree (la directory e le sue sotto-directory) o solo alla root (la
directory specificata).
Se bWatchSubtree = True, vengono monitorate anche le subdir.
dwNotifyFilter permette di specificare quali eventi devono essere
monitorati. E' un valore determinato dalla somma di queste costanti:
-        Modifiche al nome del file. Include creazione, rinomina, cancellazione.
Public Const FILE_NOTIFY_CHANGE_FILE_NAME As Long = &H1
-        Modifiche al nome delle directory. Stesse operazioni.
Public Const FILE_NOTIFY_CHANGE_DIR_NAME As Long = &H2
-        Modifiche algli attributi dei file/directory
Public Const FILE_NOTIFY_CHANGE_ATTRIBUTES As Long = &H4
-       Modifiche alla dimensione del file. Da notare che la notifica
        della variazione di dimensioni viene notificata solo quando il
         file viene scritto su disco. La cache può influire su tempi e modi
         della notifica.
Public Const FILE_NOTIFY_CHANGE_SIZE As Long = &H8
-        Modifiche alla data del file. Stesse note in relazione alla cache.
Public Const FILE_NOTIFY_CHANGE_LAST_WRITE As Long = &H10
Public Const FILE_NOTIFY_CHANGE_LAST_ACCESS As Long = &H20
Public Const FILE_NOTIFY_CHANGE_CREATION As Long = &H40
-        Modifiche al security-descriptor (solo WinNT)
Public Const FILE_NOTIFY_CHANGE_SECURITY As Long = &H100
-        Una possibile combinazione di opzioni di monitoraggio
Public Const FILE_NOTIFY_FLAGS = _
                          FILE_NOTIFY_CHANGE_ATTRIBUTES Or _
                          FILE_NOTIFY_CHANGE_FILE_NAME Or _
                          FILE_NOTIFY_CHANGE_LAST_WRITE
La funzione restituisce l'handle di un "file notification object".
Questo handle può essere passato ad una delle "Wait Functions",
funzioni che una volta chiamate, ritornano solo quando si verifica
uno degli eventi per cui sono state invocate .
Nel caso, deve essere usata WaitForMultipleObjects() oppure
WaitForMultipleObjectsEx(). Il prototipo della prima funzione
è il seguente:
Public Declare Function WaitForMultipleObjects Lib "kernel32" ( _
        ByVal nCount As Long, _
        lpHandles As Long, _
        ByVal bWaitAll As Long, _
        ByVal dwMilliseconds As Long) As Long
nCount è il numero di handles che vengono specificati in lpHandles;
Il numero massimo di handle è:
Public Const MAXIMUM_WAIT_OBJECTS As Long = 64
lpHandles è un array di Long in cui viene specificato l'elenco degli
handle che la funzione deve gestire.
bWaitAll è un valore booleano. Se = True, la funzione ritorna solo
quando si è verificato un evento per tutti gli handle definiti. Altrimenti
ritorna al primo evento che si verifica per uno degli handle (oggetti).
In questo caso, il valore dell'evento ritornato sarà incrementato del
valore dell'indice dell'handle che ha determinato l'evento.
Ossia, se si genera un evento, la funzione restituisce WAIT_OBJECT:
il valore della costante è &H0. A questo valore viene aggiunto l'indice
dell'array lpHandles, per indicare a quale oggetto ha generato l'evento.
Se WAIT_OBJECT = 0, è il primo handle dell'array, se = 1 è il secondo
e così via.
dwMilliseconds è il periodo di tempo di attesa, espresso in millisecondi,
prima che si generi un timeout. Serve per limitare il periodo di notifica
di evento ad un tempo determinato. E' possibile specificare un tempo di
attesa = INFINITE, in questo caso il timeout non si verifica mai.
Public Const INFINITE = &HFFFF
La funzione restituisce uno dei seguenti valori:
Public Const WAIT_OBJECT = &H0
Si è verificato un evento. Come indicato in precedenza, questo
è in effetti il valore minimo di WAIT_OBJECT. Ossia è il valore
restiuito nel caso bWaitAll = True oppure bWaitAll = False e
l'evento interessa il primo handle specificato. Altrimenti può
assumere valori superiori fino al massino indicato da nCount.
Public Const WAIT_TIMEOUT = &H102
Il periodo di tempo specificato da dwMilliseconds è trascorso
senza che si siano verificati eventi.
Public Const WAIT_FAILED = &HFFFF
La funzione non ha avuto successo. Occorre chiedere a
GetLastError() perché non ha funzionato.
Dopo che un evento WAIT_OBJECT si è verificato, per continuare
a monitore gli eventi successivi, occorre chiamare la funzione
FindNextChangeNotification(), passando l'handle ottenuto in
precedenza da FindFirstChangeNotification().
La funzione restituisce un nuovo handle che va passato a
WaitForMultipleObjects() per continuare il monitoraggio.
Il complessità nasce dal fatto che le Wait Function sono funzioni
blocking, ossia bloccano il processo che le ha invocate, fino al
momento in cui ritornano per il verificarsi di un evento o per un
timeout. Per quanto riguarda VB, questo significa che l'intera
applicazione viene bloccata e l'utente non può interagire.
Una scappatoia consiste nel creare due applicazioni. La prima
applicazione (o processo) contiene le funzioni di monitoraggio
degli eventi, ila secondo processo viene avviato dalla primo.
Essendo un processo a se stante, non viene bloccato, fornendo
così un mezzo per terminare il primo processo (processo chiamante).
In pratica:
Avvio il processo primario.
Prima di inizializzare la sequenza di monitoraggio, avvio il secondo
processo tramite Shell e lo sincronizzo tramite OpenProcess().
Passo l'handle del processo, restituito da OpenProcess(), alla
Wait Function insieme agli handle degli eventi da monitorare.
Quando il secondo processo - interattivo - viene terminato, la
Wait Function ritorna perché si è generato un evento associato
al processo e ho modo di terminare il primo processo, visto che
il controllo viene restituito.
In pseudo-codice:
================================================
Public Declare Function FindCloseChangeNotification Lib "kernel32" _
   (ByVal hObjectHandle As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
Public Const SYNCHRONIZE = &H100000
[Parent Process]
    [ProcessID] = Shell([ApplicationName], vbNormalNoFocus)
    [ProcessHandle] = OpenProcess(SYNCHRONIZE, 0, [ProcessID])
    If [ProcessHandle] Then
        [ObjectHandle] = FindFirstChangeNotification( _
                                    [PathName], _
                                    False, _
                                    FILE_NOTIFY_FLAGS)
    Else
        ' Errore
        ' Fine processo
        Call FindCloseChangeNotification([ObjectHandle])
        Call CloseHandle([ProcessHandle])
        Exit [ParentProcess]
    End IF
    ' Watch del primo evento
    lngRet = [WaitFunctionWrapper]( _
                  [ObjectHandle], _
                  [ProcessHandle])
    Select Case lngRet
    Case WAIT_OBJECT
        ' Notifica di un evento relativo alla directory in watch
        '-----------------------------------------------------
        ' Primo evento notificato. Operazioni da compiere.
        '-----------------------------------------------------
        ' Si continua il processo di monitoraggio
        Do While lngRet <> WAIT_TIMEOUT
            Call FindNextChangeNotification([ObjectHandle])
             ' Watch degli eventi successivi
             lngRet = [WaitFunctionWrapper]( _
                          [ObjectHandle], _
                          [ProcessHandle])
             '======================
             ' Casi legati agli eventi successivi
             '======================
             Select Case lngRet
             Case WAIT_OBJECT
                 ' Notifica di un evento relativo alla directory in watch
                 '-----------------------------------------------------
                 ' Eventi successivi. Operazioni da compiere.
                 '-----------------------------------------------------
             Case WAIT_OBJECT +1
                 ' Il processo secondario è terminato
                 ' Fine programma
              Case WAIT_FAILED
                  ' Il programma è stato terminato o si è verificato
                  ' un altro tipo di errore.
               End Select
            Loop
    '=====================
    ' Altri casi legati al primo evento
    '=====================
    Case WAIT_OBJECT +1
        ' Il processo secondario è terminato
        ' Fine programma
    Case WAIT_FAILED
        ' Il programma è stato terminato o si è verificato
        ' un altro tipo di errore.
    End Select
    Call FindCloseChangeNotification([ObjectHandle])
    Call CloseHandle([ProcessHandle])
End [ParentProcess]
=========================================
[WaitFunctionWrapper] ([ObjectHandle] As Long, _
                                      [ProcessHandle] As Long) As Long
Dim arrHandles(1)
Dim lngRet As Long
    arrHandles(0) = [ObjectHandle]
    arrHandles(1) = [ProcessHandle]
    [On Error Resume Next]
    Do While lngRet = WAIT_TIMEOUT
        lngRet = WaitForMultipleObjects( _
                      Ubound(arrHandles) - 1, _
                      arrHandles(0); _
    Loop
End [WaitFunctionWrapper]
=========================================

 =========================================