Page 1 sur 1
[UDF] RMonitor: surveillance d'un dossier
Posté : mer. 22 mai 2013 21:42
par mano78170
Pourquoi ne pas pouvoir surveiller les modifications d'un dossier ?
[Je, tu, ils... sont parano]
Cet UDF répond simplement à cette question: miaintenant OUI !
Une fois correctement configuré, il appellera une fonction
callback à chaque:
- Création
- Suppression
- Modification
- Changement de nom
de n'importe quel fichier ou dossier à l'intérieur de celui configuré (oui, oui, c'est récursif !
)
2 modes sont possibles:
- Attente d'un évenement
La fonction d'attente est appelé une unique fois et appellera la callback dès qu'un unique évènement se produira
- Surveillance continue
Un thread est lancé et appellera la callback autant de fois qu'il le faudra !
Miais un bon exemple est surement plus efficace qu'un long
et potentiellement chiant discours !
► Afficher le texteexemple
Code : Tout sélectionner
#include "RepMonitor.au3"
; Configuration:
; On va surveiller mon bureau...
RMonitor_SetFolder("C:\Users\Jon\Desktop\")
; ...en appelant _TestCalback à chaque évènement
RMonitor_SetCallback("_TestCallback")
; ### EXEMPLE 1: Attente d'un évènement ###
While 1
; La boucle est interrompue à chaque attente
RMonitor_WaitForEvents()
WEnd
; ### EXEMPLE 2: Surveillance continue ###
RMonitor_StartMonitoring()
While 1
; La boucle est continue
WEnd
RMonitor_StopMonitoring()
; Notre callback favorite:
; Un seul argument de type wstr
; Prototype C:
; void _TestCallback(const wchar_t MSG);
; void _TestCallback(LPCWSTR MSG); (en WINAPI)
Func _TestCallback($MSG)
; 1er caractère = ID de l'évènement
Local $EventID = StringLeft($MSG, 1), _
$CompletePath = "C:\Users\Jon\" & StringTrimLeft($MSG, 1)
; Reste = Chemin RELATIF du dossier|fichier
Static $OldName
Switch ($EventID)
Case $FILE_ACTION_ADDED
ConsoleWrite("Ajout: " & $CompletePath & @CRLF)
Case $FILE_ACTION_REMOVED
ConsoleWrite("Suppression: " & $CompletePath & @CRLF)
Case $FILE_ACTION_MODIFIED
ConsoleWrite("Modification: " & $CompletePath & @CRLF)
Case $FILE_ACTION_RENAMED_OLD_NAME
$OldName = $CompletePath
Case $FILE_ACTION_RENAMED_NEW_NAME
ConsoleWrite("Renommé: " & $OldName & " en " & $CompletePath & @CRLF)
EndSwitch
EndFunc
Toute la demiarche étant gérée par la DLL, pas besoin de se préoccuper du pourquoi du comment !
(Techniquement parlant (pour les fadas du C), c'est du bon pointeur sur fonction le tout dans un thread
)
NB:
La DLL à été codée par mes soins, donc aucun danger à ce niveau là !
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mer. 22 mai 2013 21:55
par Tlem
Bonsoir et merci du partage.
Pour info, il existe une version qui utilise les API Windows et donc sans DLL (Full AutoIt) ici :
http://www.autoitscript.com/forum/topic ... onitor-udf
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mer. 22 mai 2013 22:06
par mano78170
Merci pour l'info, j'avais déjà testé cet UDF, qui, à mia grande déception ne semble pas fonctionner à tout les coups
Il utilise effectivement la même fonction que moi (ReadDirectoryChangeW) miais ne permet pas le multithreading
(Concept assez dur à implémenter proprement en 100% AutoIt)
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : jeu. 23 mai 2013 02:27
par matwachich
Je pense que la différence avec l'UDF WinAPI est la récursivité (je peux me tromper ...)
Sinon, est-ce possible d'avoir le code de la DLL?
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : jeu. 23 mai 2013 20:01
par mano78170
La récursivité n'est qu'un paramètre booléen à passer à
ReadDirectoryChangesW
(vous le trouverez d'ailleurs à la ligne 100
)
En ce qui concerne l'implémentation de cette fonction, rien de bien vraiment compliqué à l'exception du buffer de structure FILE_NOTIFY_INFORMATION
qui lui à été le véritable truc
chiant embêtant (passé en temps que *DWORD[], y'a des fois on se demiande ce que les dev de chez MS ont
dans la tête
)
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : dim. 26 mai 2013 22:19
par matwachich
Je suis d'accord à propos des dev de M$.
Merci beaucoup pour le code, et le projet CB!
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : lun. 27 mai 2013 21:02
par mano78170
Quand un dev trouve une bonne idée, il n'y a aucune raison pour qu'il la garde pour lui seul !
En d'autre termes, je soutient l'open source
De plus, il est évident que cette DLL n'est pas parfaite ! Et c'est en partageant son code qu'elle le deviendra (hypothétiquement) un jour !
Je demiande juste que si quelqu'un souhaite réutiliser ce code, il me cite en tant qu'auteur (juste pour le swag d'avoir codé un truc un peu utile
pour changer )
Au fait, pour ceux qui souhaiteraient obtenir un DllMain 'propre' (pas un DllMain@12 quoi), il suffit de passer le param
-Wl,--kill-at au linker !
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mar. 28 mai 2013 01:52
par matwachich
Quand j'aurai un peu de temps, je compte modifier votre code pour pouvoir surveiller plusieurs dossiers, configurer la récursivité ...
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mar. 20 août 2013 17:27
par Cautex
Bonjour,
Merci pour cet udf mais chez moi il ne fonctionne que partiellement:
1. la partie "; ### EXEMPLE 2: Surveillance continue ###" plante à chaque fois;
2. pour l'exemple 1, tout marche sauf la détection de fichier modifié ou la fonction "_TestCallback($MSG)" n'est pas appelée .
EDIT: j'ai testé le "FileSystemMonitor UDF" et il ne retourne pas non plus la modification de fichier chez moi.
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mer. 21 août 2013 02:43
par mano78170
Bonjour,
Il est possible que mon UDF loupe effectivement de façon occasionnel certains events, les modifications entre autre car elles peuvent être générées en nombre dans un cour laps de temps, ce qui suffit à provoquer un buffer overload au sein de la dll et donc en zapper quelques unes. Après, ce système se basant uniquement sur la WinAPI, il est possible que l'os ne hook pas absolument TOUT les events...
Concernant le crash du second exemple, c'est la première fois que l'on signale un tel bug, aussi je ne peux que vous rappeler que les appels des fonctions
RMonitor_SetFolder et
RMonitor_SetCallback sont à effectuer impérativement
avant de déclencher le monitoring (et ceux dans les 2 cas).
Vous disposez également du code complet de la DLL (quelques messages plus haut) si vous souhaitez "tester/titiller" les fonctions C.
En cas de bugfix, je vous serais reconnaissant de poster le code mis à jour.
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : lun. 16 mai 2016 10:57
par Deathmask04
Bonjour,
J'ai un petit problème lorsque je scan un répertoire via un lecteur réseau en utilisant la fonction RMonitor_StartMonitoring(), si le lecteur réseau devient inaccessible, mon programme plante (AutoIt3exe ended.rc:-1073741819)
Avez vous une solution ?
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mer. 18 mai 2016 01:05
par mano78170
Bonjour,
Cela fait un bon moment que je n'ai pas fais d'AutoIt (majoritairement à cause de ma conversion vers le monde merveilleux de Linux).
Cependant si vous avez quelques connaissances en C (et potentiellement WinAPI), vous pouvez télécharger le code source de ma DLL
(disponible à ce post:
http://www.autoitscript.fr/forum/viewto ... c14#p78138)
En cas de patch/fix je vous demande juste de partager vos sources sur ce thread (et/ou sur tout autre site) en me citant en tant qu'auteur dans le code.
Si vous avez une question sur le code ou autre, je reste disponible par MP.
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : mar. 26 févr. 2019 19:28
par Amesamana
Bonjour,
Bon tardivement par rapport à la date du sujet, mais très utile pour vérifier l'ajout et la suppression des fichiers pour l'élaboration de code.
Je vais essayer de l'adapter à une GUI.
it 's excellent
Re: [UDF] RMonitor: surveillance d'un dossier
Posté : dim. 18 août 2019 23:13
par marcgforce
Bonsoir,
Je rebondis sur le sujet, car j'ai créé sur la base du script d'exemple, un monitoring de répertoire présent dans le systray qui envoi un traytip ou un toast dès qu'un fichier est créé modifié ou supprimé, malheureusement, la DLL n'est pas stable et lorsque plusieurs événements arrivent en même temps ou dans un temps très rapproché (plusieurs ajouts, plusieurs suppressions) le script plante et quitte silencieusement, n’étant pas calé en C, je laisse a l'auteur de la DLL le soin de la correction, car en refaisant le script sur la base de l'UDF FileSystemMonitor.au3 tout fonctionne correctement et les événements sont traités les uns après les autres.
Le lien vers filesystemmonitor
je laisse les scripts au cas ou...
le script utilisant la DLL
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****#AutoIt3Wrapper_Icon=..\Users\Marc\Pictures\icones\folder_survey.ico#AutoIt3Wrapper_Outfile=surveillance.exe#AutoIt3Wrapper_Res_Comment=Surveillance de dossier pour le CIC#AutoIt3Wrapper_Res_Description=Surveillance de dossier pour le CIC#AutoIt3Wrapper_Res_Fileversion=1.0.0.1#AutoIt3Wrapper_Res_Language=1036#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****#include <RepMonitor.au3>#include <TrayConstants.au3>#include
<Array
.au3>#include
<toast
.au3>FileInstall("C:\devellopement_au3\Rmonitor.dll",".\")Opt("TrayMenuMode", 3)Global $surveillance_rep ="", $sfile =""Dim $last_event[1]=["Aucun évènement à afficher"]$configuration = TrayCreateItem("Configuration")TrayCreateItem("")$fileconfig = @ScriptDir & "\confsurvey.ini"$findfile = FileFindFirstFile($fileconfig)If $findfile = -1 Then Msgbox(0,"Surveillance - Selection du dossier", "Veuillez sélectionner le réperoire à surveiller") $Folder_selected = FileSelectFolder("Selectionner le répertoire à surveiller",@DesktopDir) if @error = 1 then msgbox(64,"Erreur ! ","Aucun répertoire séléctionné, je quitte !",3) Exit EndIf IniWriteSection($fileconfig, "config", "chemin=" & $Folder_selected) $sfile = IniRead($fileconfig, "config", "chemin", @MyDocumentsDir) $surveillance_rep=$sfileElse $sfile = IniRead($fileconfig, "config", "chemin", @MyDocumentsDir) $surveillance_rep=$sfileEndIfTrayCreateItem("Dossier surveillé :")$survey=TrayCreateItem($surveillance_rep)TrayCreateItem("")$tray_lastEvent = TrayCreateItem("Dernier évenement")TrayCreateItem("")$about = TrayCreateItem("A propos")$exit = TrayCreateItem("Quitter")TraySetState($TRAY_ICONSTATE_SHOW); Initialisation du répertoire à surveillerRMonitor_SetFolder
($surveillance_rep); ...en appelant _TestCalback à chaque évènementRMonitor_SetCallback
("_TestCallback")_Toast_Set
(-1, -1, -1, -1, -1, 15)_Toast_Show
(0, "Surveillance de : " & $surveillance_rep, "Demarrage de la surveillance du dossier...",3)_Toast_Hide
();Attente d'un évènement;While 1 ; La boucle est interrompue à chaque attente ; RMonitor_WaitForEvents();WEnd; Surveillance en continueRMonitor_StartMonitoring
()While 1 $msg = trayGetMsg() Select Case $msg = $exit _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "A bientôt", "Merci d'avoir utilisé ce logiciel...", 3) _Toast_Hide
() RMonitor_StopMonitoring
() Exit Case $msg = $about MsgBox (-1,"Surveillance", "Surveillance de dossier (Ajout, Suppr , modifs de fichiers)" & @CRLF & "Avertissement par infobulle") case $msg = $configuration $question = Msgbox(1,"Surveillance","Voulez vous surveiller un dossier different ?") if $question = 1 then $Folder_selected = FileSelectFolder("Selectionner le répertoire à surveiller",@DesktopDir) IniWriteSection($fileconfig, "config", "chemin=" & $Folder_selected) _RestartProgram
(); lors d'un changement des paramètres de surveillance un self-retart est requis EndIf Case $msg = $tray_lastEvent _Toast_Set
(-1, -1, -1, -1, -1, 15) ;TrayTip("Surveillance de : " & $surveillance_rep,$last_event[0],30) _Toast_Show
(0, "Surveillance de : " & $surveillance_rep, $last_event[0], 20) _Toast_Hide
() EndSelect ;La boucle est continueWEnd;RMonitor_StopMonitoring(); Notre callback favorite:; Un seul argument de type wstr; Prototype C:; void _TestCallback(const wchar_t MSG);; void _TestCallback(LPCWSTR MSG); (en WINAPI)Func _TestCallback
($MSG) ;$surveillance_rep = $surveillance_rep ; 1er caractère = ID de l'évènement Local $EventID = StringLeft($MSG, 1), _
$CompletePath = $surveillance_rep &"\" & StringTrimLeft($MSG, 1) ; Reste = Chemin RELATIF du dossier|fichier Static $OldName Switch ($EventID) Case $FILE_ACTION_ADDED ;SoundPlay(@WindowsDir & "\media\alarm09.wav") TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $CompletePath & " vient d'être créé",1) $last_event[0]="Le fichier " & $CompletePath & " vient d'être créé" Case $FILE_ACTION_REMOVED ;SoundPlay(@WindowsDir & "\media\alarm09.wav") TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $CompletePath & " vient d'être supprimé",30) $last_event[0]="Le fichier " & $CompletePath & " vient d'être supprimé" Case $FILE_ACTION_MODIFIED ;SoundPlay(@WindowsDir & "\media\alarm09.wav") TrayTip("Surveillance de : " & $surveillance_rep, "Le fichier " & $CompletePath & " vient d'être modifié",30) $last_event[0]="Le fichier " & $CompletePath & " vient d'être modifié" Case $FILE_ACTION_RENAMED_OLD_NAME $OldName = $CompletePath Case $FILE_ACTION_RENAMED_NEW_NAME ;SoundPlay(@WindowsDir & "\media\alarm09.wav") TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $OldName & " vient d'être renomé en " & $CompletePath,30) $last_event[0]= "Le fichier " & $OldName & " vient d'être renomé en " & $CompletePath EndSwitchEndFunc#Region --- Restart Program --- Func _RestartProgram
() If @Compiled = 1 Then Run(FileGetShortName(@ScriptFullPath)) Else Run(FileGetShortName(@AutoItExe) & " " & FileGetShortName(@ScriptFullPath)) EndIf Exit EndFunc; ==> _RestartProgram#EndRegion --- Restart Program ---
le nouveau code utilisant l'UDF Filesystemmonitor.au3
#include <TrayConstants.au3>#include
<toast
.au3>#include <FileSystemMonitor.au3>Opt("TrayMenuMode", 3)Global $surveillance_rep ="", $sfile ="", $old_item, $old_name, $CompletePathDim $last_event[1]=["Aucun évènement à afficher"]$configuration = TrayCreateItem("Configuration")TrayCreateItem("")$fileconfig = @ScriptDir & "\confsurvey.ini"$findfile = FileFindFirstFile($fileconfig)If $findfile = -1 Then Msgbox(0,"Surveillance - Selection du dossier", "Veuillez sélectionner le réperoire à surveiller") $Folder_selected = FileSelectFolder("Selectionner le répertoire à surveiller",@DesktopDir) if @error = 1 then msgbox(64,"Erreur ! ","Aucun répertoire séléctionné, je quitte !",3) Exit EndIf IniWriteSection($fileconfig, "config", "chemin=" & $Folder_selected) $sfile = IniRead($fileconfig, "config", "chemin", @MyDocumentsDir) $surveillance_rep=$sfileElse $sfile = IniRead($fileconfig, "config", "chemin", @MyDocumentsDir) $surveillance_rep=$sfileEndIfTrayCreateItem("Dossier surveillé :")$survey=TrayCreateItem($surveillance_rep)TrayCreateItem("")$tray_lastEvent = TrayCreateItem("Dernier évenement")TrayCreateItem("")$about = TrayCreateItem("A propos")$exit = TrayCreateItem("Quitter")TraySetState($TRAY_ICONSTATE_SHOW)_FileSysMonSetup
(1,$surveillance_rep,$surveillance_rep); Initialisation du répertoire à surveiller_Toast_Set
(-1, -1, -1, -1, -1, 15)_Toast_Show
(0, "Surveillance de : " & $surveillance_rep, "Demarrage de la surveillance du dossier...",3)_Toast_Hide
()While 1 _FileSysMonDirEventHandler
() $msg = trayGetMsg() Select Case $msg = $exit _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "A bientôt", "Merci d'avoir utilisé ce logiciel...", 3) _Toast_Hide
() Exit Case $msg = $about MsgBox (-1,"Surveillance", "Surveillance de dossier (Ajout, Suppr , modifs de fichiers)" & @CRLF & "Avertissement par infobulle") case $msg = $configuration $question = Msgbox(1,"Surveillance","Voulez vous surveiller un dossier different ?") if $question = 1 then $Folder_selected = FileSelectFolder("Selectionner le répertoire à surveiller",@DesktopDir) IniWriteSection($fileconfig, "config", "chemin=" & $Folder_selected) _RestartProgram
(); lors d'un changement des paramètres de surveillance un self-retart est requis EndIf Case $msg = $tray_lastEvent _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "Surveillance de : " & $surveillance_rep, $last_event[0], 20) _Toast_Hide
() EndSelect WEndFunc _FileSysMonActionEvent
($event_type, $event_id, $event_value) $CompletePath = $surveillance_rep &"\" & $event_value ;ConsoleWrite($event_type & "|" & $event_id & "|" & $event_value & @CRLF) Switch $event_type case 0 Switch $event_id Case 0x00000001 ; file / folder added ;ConsoleWrite("adding file / folder " & $event_value & @CRLF) SoundPlay(@WindowsDir & "\media\alarm09.wav") ;TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $CompletePath & " vient d'être créé",1) _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "Surveillance de : " & $surveillance_rep, "Le fichier " & $CompletePath & " vient d'être créé", 20) _Toast_Hide
() $last_event[0]="Le fichier " & $CompletePath & " vient d'être créé" ; If the item is a folder ;if StringInStr(FileGetAttrib(GUICtrlRead($path_input) & $event_value), "D") > 0 Then $event_value = "<DIR> " & $event_value Case 0x00000002 ; file removed ;ConsoleWrite("removing file " & $event_value & @CRLF) SoundPlay(@WindowsDir & "\media\alarm09.wav") ;TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $CompletePath & " vient d'être supprimé",30) _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "Surveillance de : " & $surveillance_rep, "Le fichier " & $CompletePath & " vient d'être supprimé", 5) _Toast_Hide
() $last_event[0]="Le fichier " & $CompletePath & " vient d'être supprimé" Case 0x00000004 ; file / folder renamed - old name $old_item = $event_value Case 0x00000005 ; file / folder renamed - new name ;ConsoleWrite("renaming file " & $old_item & " to " & $event_value & @CRLF) SoundPlay(@WindowsDir & "\media\alarm09.wav") ;TrayTip("Surveillance de : " & $surveillance_rep,"Le fichier " & $old_item & " vient d'être renomé en " & $CompletePath,30) _Toast_Set
(-1, -1, -1, -1, -1, 15) _Toast_Show
(0, "Surveillance de : " & $surveillance_rep, "Le fichier " & $old_item & " vient d'être renomé en " & $CompletePath, 10) _Toast_Hide
() $last_event[0]= "Le fichier " & $old_item & " vient d'être renomé en " & $CompletePath EndSwitch EndSwitchEndFunc#Region --- Restart Program --- Func _RestartProgram
() If @Compiled = 1 Then Run(FileGetShortName(@ScriptFullPath)) Else Run(FileGetShortName(@AutoItExe) & " " & FileGetShortName(@ScriptFullPath)) EndIf Exit EndFunc; ==> _RestartProgram#EndRegion --- Restart Program ---