Seite 1 von 1

Überwachung eines Ordners im Hintergrund

Verfasst: 18.07.2013 14:18
von Piwo
Hi Leute,

ich möchte ein Programm schreiben, welches ein vom user angegebenen ordner kontinuierlich überwacht und reagiert sobald neue Dateien reingespeichert werden, Dateien gelöscht oder verändert werden. Das anfürsich ist nicht unbedingt das problem, aber ich wollte dass beim schließen des hauptfensters des programms, es als icon unten rechts in der symbolleiste landet (OS: windows).
In dieser leiste soll man natürlich jederzeit das hauptfenster wieder öffnen können, das programm soll aber in der zweischenzeit dauerhaft seine überwachung fortsetzen. Meine Fragen hierzu jetzt:

- Wie realisiere ich es dass das programm als icon unten rechts auftaucht und von da aus seine arbeit normal verrichtet?
- Um möglichst CPU-schonend vorzugehen sollte ich die ordner-kontrolle lieber in einer festgelegten Frequenz abarbeiten lassen? (z.B. alle 2 sekunden ein check)
- Was wäre wohl die einfachste und efizienteste methode um in einem Ordner samt Unterordner auf diese 3 events anzusprechen (neue datei, gelöschte datei, veränderte datei)?

Danke im vorraus :)

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 18.07.2013 14:36
von Kevin
Hi,

Code: Alles auswählen

;Autor: jpfiste

EnableExplicit

Define EventID

#FILE_NOTIFY_CHANGE_FILE_NAME = 1
#FILE_NOTIFY_CHANGE_DIR_NAME = 2
#FILE_NOTIFY_CHANGE_ATTRIBUTES = 4
#FILE_NOTIFY_CHANGE_SIZE = 8
#FILE_NOTIFY_CHANGE_LAST_WRITE = $10
#FILE_NOTIFY_CHANGE_LAST_ACCESS = $20
#FILE_NOTIFY_CHANGE_CREATION = $40
#FILE_NOTIFY_CHANGE_SECURITY = $100
#FILE_NOTIFY_CHANGE_ALL = $17F
#FILE_SHARE_DELETE = 4
#FILE_ACTION_ADDED = 1
#FILE_ACTION_REMOVED = 2
#FILE_ACTION_MODIFIED = 3
#FILE_ACTION_RENAMED_OLD_NAME = 4
#FILE_ACTION_RENAMED_NEW_NAME = 5

Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{255}
EndStructure

Import "kernel32.lib"
  ReadDirectoryChangesW(a, b, c, d, e, f, g, h)
EndImport

Global WatchPath$=GetTemporaryDirectory()

Procedure WatchDirOrFile(z)
  Protected DirectoryName.s="C:\"
  Protected NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL
  Protected buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
  Protected FileAction_Filename.s
  Protected hDir
  Protected bytesRead
  Protected path$
  
  hDir = CreateFile_(DirectoryName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  
  While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
    
    FileAction_Filename = PeekS(@buffer\Filename, -1, #PB_Unicode)
    
    path$=GetPathPart(DirectoryName+FileAction_Filename)
    If FindString(path$,WatchPath$)
      
      Select buffer\Action
        Case #FILE_ACTION_ADDED
          AddGadgetItem(2,-1,"Added: " + DirectoryName.s + FileAction_Filename,0,0)
        Case #FILE_ACTION_REMOVED
          AddGadgetItem(2,-1,"Removed: " + DirectoryName.s + FileAction_Filename,0,0)
        Case #FILE_ACTION_MODIFIED
          AddGadgetItem(2,-1,"Modified: " + DirectoryName.s + FileAction_Filename,0,0)
        Case #FILE_ACTION_RENAMED_OLD_NAME
          ;Dateiumbenennung: Alter Dateiname
        Case #FILE_ACTION_RENAMED_NEW_NAME
          ;Dateiumbenennung: Neuer Dateiname
      EndSelect
    EndIf
    
    buffer\Filename = ""
    
  Wend
  
EndProcedure

Define Hidden = 0
If OpenWindow(0,0,0,500,400,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  TextGadget(1,10,10,WindowWidth(0),20,"Veränderungen auf "+WatchPath$+":",0)
  EditorGadget(2,10,30,WindowWidth(0)-20,WindowHeight(0)-60,0)
  ButtonGadget(3,10,WindowHeight(0)-25,WindowWidth(0)-20,20,"end")
  CreateThread(@WatchDirOrFile(),0)
  
  CreateImage(0,16,16)
  AddSysTrayIcon(0, WindowID(0), ImageID(0))
  
  Repeat
    
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Hidden!1 : HideWindow(0, Hidden)
      Case #PB_Event_SysTray
        Hidden!1 : HideWindow(0, Hidden)
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 3
            End
        EndSelect
    EndSelect
  ForEver
EndIf
mfg
kevin

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 09:15
von dige
Achtung, der Code muss noch erweitert werden, da im Buffer auch mehrere Dateiänderungen gemeldet werden können.
D.h. der Buffer sollte mind. 4K groß sein und NextEntryOffset muss geprüft werden.

Am besten einfach mal 100 Dateien vom gleichen Laufwerk auswählen und in Dein überwachtes Verzeichnis schieben.
Wenn dann 100 #FILE_ACTION_ADDED Events ermittelt wurden, funktioniert die Überwachung ;-)

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 09:36
von TheCube
<) Fein, so ein Codeschnippsel habe ich als Start gerade gebraucht.

Aber in der Prozedur "WatchDirOrFile()" die Variable DirectoryName.s="C:\" zu setzen
dürfte ein Fehler sein.
Besser :

Code: Alles auswählen

Procedure WatchDirOrFile(z)
  Protected DirectoryName.s=WatchPath$
  ...........
So funktionierts bei mir dann.

Dige´s Anmerkung kann ich aber grad nicht verstehen ... :coderselixir:

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 14:25
von Sicro
dige hat geschrieben:Achtung, der Code muss noch erweitert werden, da im Buffer auch mehrere Dateiänderungen gemeldet werden können.
D.h. der Buffer sollte mind. 4K groß sein und NextEntryOffset muss geprüft werden.
Im Code ist das so schon richtig. Der buffer hat in dem Code Speicher für einmal die definierte Struktur. Diese Größe wird auch der Funktion "ReadDirectoryChangesW" übergeben und diese füllt den Buffer auch nur bis zur Buffer-Größe. Weitere Änderungen werden dann halt beim nächsten Aufruf von "ReadDirectoryChangesW" erhalten. NextEntryOffset muss also nur berücksichtigt werden, wenn der buffer Platz für mehr Einträge hat. Das ist aber in dem Code oben nicht gegeben.

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 18:30
von dige
Wenn nur ein Name übergeben werden kann, führt das imho zu Informationsverlusten.
Daher mein Beispiel mit einem Rutsch 100 Dateien zu verschieben und zu prüfen, ob jede
Datei gemeldet wurde.

Ciao Dige

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 18:58
von Sicro
Habe es gerade mal mit 100 Dateien ausprobiert und konnte keine Informationsverluste feststellen.
Getestet habe ich Hinzufügen, Löschen und Umbenennen.
Windows 7 Home 64-Bit

Re: Überwachung eines Ordners im Hintergrund

Verfasst: 19.07.2013 19:10
von RSBasic
Ich nutze den Code für meine Anwendung täglich und konnte ebenfalls keine Informationsverluste feststellen.