Überwachung eines Ordners im Hintergrund

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Piwo
Beiträge: 27
Registriert: 05.08.2012 22:40

Überwachung eines Ordners im Hintergrund

Beitrag 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 :)
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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
Benutzeravatar
dige
Beiträge: 1235
Registriert: 08.09.2004 08:53

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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 ;-)
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
TheCube
Beiträge: 169
Registriert: 20.07.2010 23:59
Computerausstattung: Risen 3400G 16MB Win10-64Bit
Wohnort: NRW

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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:
Benutzeravatar
Sicro
Beiträge: 963
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
dige
Beiträge: 1235
Registriert: 08.09.2004 08:53

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
Sicro
Beiträge: 963
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Überwachung eines Ordners im Hintergrund

Beitrag 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
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Überwachung eines Ordners im Hintergrund

Beitrag von RSBasic »

Ich nutze den Code für meine Anwendung täglich und konnte ebenfalls keine Informationsverluste feststellen.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten