Ordner Überwachung

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Ordner Überwachung

Beitrag von silbersurfer »

Hallo Leute,
in meinen Filemanager Projekt habe ich eine Ordnerüberwachung eingefügt, die mit
hilfe von dem API Befehl FindFirstChangeNotification und WaitForSingleObject
auch umgesetzt habe.

Code: Alles auswählen

tructure Look ; Verzeichnisüberwachung
	Thread.i : Gadget.i
 	Directory.s
 	Milliseconds.l
 	stop.i
EndStructure



Procedure VerzeichnisUeberwachung(*SLook.Look)
	Protected exit.l,refresh.i,datein.i,backup.i
	Debug "Watch auf "+*SLook\Directory + " gestartet !"
	While exit = 0	
		If *SLook\Gadget=ExplorerList_0		
			hchangeobject0=FindFirstChangeNotification_(*SLook\Directory,0,3)
			If WaitForSingleObject_(hchangeobject0,*SLook\milliseconds)= 0 
				datein=1
				If *slook\stop
					;soll den Überwachungs Thread beenden
					FindCloseChangeNotification_(hchangeobject0)	
					exit=1
					Break
				EndIf 						
			Else 
				backup=1
				If datein
					If backup
						backup=0 : datein=0
						;dient dem Refresh des ListGadget0
						PostEvent(#MyWatchFolder,Pure_Commander,0,0,*SLook)	
					EndIf 
				EndIf 
			EndIf	
			FindNextChangeNotification_(hchangeobject0)
		ElseIf *SLook\Gadget=ExplorerList_1
			hchangeobject1=FindFirstChangeNotification_(*SLook\Directory,0,3)
			If WaitForSingleObject_(hchangeobject1,*SLook\milliseconds)= 0 
				datein=1
				If *slook\stop
					FindCloseChangeNotification_(hchangeobject0)	
					exit=1
					Break
				EndIf 
			Else 
				backup=1
				If datein
					If backup
						backup=0 : datein=0
						;dient dem Refresh des ListGadget1
						PostEvent(#MyWatchFolder,Pure_Commander,0,0,*SLook)	
					EndIf 
				EndIf 
			EndIf
			FindNextChangeNotification_(hchangeobject1)		
		EndIf 	
	Wend
EndProcedure
Dabei ist mir nun folgendes Problem aufgefallen,
1. wenn ich ein Verzeichnis mit meinen FileManger öffne so wird dieses auch korrekt überwacht,
2. sobald ich aus diesem Verzeichnis wieder raus gehe, wird mein Überwachungsthread auch sauber beendet,
3. möchte ich nun das Verzeichnis löschen, in dem ich mich voher befunden habe funzt diese nicht richtig,
4. erstelle das voher gelöschte Verzeichnis erneut, kommt es zur der Fehlermeldung Verzeichnis kann nicht erstellt werden !

Das lässt den Schuß zu, dass ich die Überwachung von FindFirstChangeNotification und WaitForSingleObject
die eigentlich mit hilfe von FindCloseChangeNotification beendet werden sollte, nicht korekt benendet habe.

Ich hoffe das ihr mir da auf die sprünge helfen könnt
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Ordner Überwachung

Beitrag von RSBasic »

Benutze lieber ReadDirectoryChangesW_(). Damit hast du viel mehr Möglichkeiten. Beispielcode siehe WinAPI Library\Datenträger-Veränderungen ermitteln
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Ordner Überwachung

Beitrag von Bisonte »

Da kann ich eigentlich gleich : SuperviseDirectory() & GetKnownFolder() [Module][WIN] empfehlen :mrgreen:
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: Ordner Überwachung

Beitrag von silbersurfer »

Erst einmal Danke, für das schelle Antworten.
@Bisnote
Da kann ich eigentlich gleich : SuperviseDirectory() & GetKnownFolder() [Module][WIN] empfehlen
Ja deinen Code kenne Ich schon, ich werde mal einiges damit testen, da ich ja immer Dynamisch die aktuellen Verzeichnisse in meinen Dateimanger überwachen lasse.

@RSBasic
Benutze lieber ReadDirectoryChangesW_()
das war ja mein erstes vorgehen RSBasic, nur konnte ich nicht meine eigenen Threads sauber beenden.
Siehe viewtopic.php?f=16&t=30754

bei meiner Procedure läuft alles einwandfrei, mein Thread wird mit einen StopBit sauber beendet.
Es scheint aber noch irgendwie auf dem Verzeichnis ein zugriff zu bestehen da dieses nicht sauber gelöscht wird.
habt hier zu keinen Ansatz für mich ?
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: Ordner Überwachung

Beitrag von silbersurfer »

Hallo Bisnote,
habe jetzt mal versucht mit deinen Modul weiter zu kommen, aber leider funtz das nicht so wie ich es gerne hätte
hier mal ein kleines Beispiel aus deiner Demo
hier möchte ich das Überwachen des Verzeichnises abbrechen, um z.B ein neues Verzeichnis zu Überwachen, das du ja mit dem Befehl
StopSuperviseDirectory() ermöglichst soweit ich das verstehe.
oder habe ich hier was übersehen ?

Code: Alles auswählen

; Demo

CompilerIf #PB_Compiler_IsMainFile
 
  EnableExplicit
 
  UseModule mAPI
 
  Enumeration #PB_Event_FirstCustomValue
    #WatchDir
  EndEnumeration
  Enumeration #PB_EventType_FirstCustomValue
    #WatchDir_Add
    #WatchDir_Mod
    #WatchDir_Del
    #WatchDir_Rename
  EndEnumeration
 
  ; Show SaveGame Directory Path
  Debug GetKnownFolderPath(#FID_SavedGames)
 
  ; Show Documents Directory Path
  Debug GetKnownFolderPath(#FID_Documents)
 
  ; Set your EventProcedure
  Procedure.i Event_WatchDir()
   
    Protected FileName.s, NewFile.s, OldFile.s
   
    If EventData()
     
      FileName = PeekS(EventData(), -1, #PB_Unicode)
     
      Select EventType()
        Case #WatchDir_Add
          Debug "File " + FileName + " was created in Directory " + GetSuperViserDirectory(EventGadget())
        Case #WatchDir_Mod
          Debug "File " + FileName + " was modified"
        Case #WatchDir_Del
          Debug "File " + FileName + " has been deleted"
        Case #WatchDir_Rename
          OldFile.s = StringField(FileName, 1, ":")
          NewFile.s = StringField(FileName, 2, ":")
          Debug "The File : " + OldFile + " was renamed to " + NewFile
      EndSelect
     
      ; Be sure, that you free the Memory !!! EventData contains an allocated memory block
      FreeMemory(EventData())
     
    EndIf
   
  EndProcedure
   
  ; Set your Event and the EventTypes
  Init_SuperVisorDirectory(#WatchDir, #WatchDir_Add, #WatchDir_Mod, #WatchDir_Del, #WatchDir_Rename)
 
  ; Open a window
  OpenWindow(0, 0, 0, 320, 200, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  ButtonGadget(0,10,10,80,20,"Stop Thread")
  ; Bind the Event
  BindEvent(#WatchDir, @Event_WatchDir(), 0)
 
  ; Start SuperVisorDirectory
  StartSuperviseDirectory("F:\Testcopy\test", 0, #False)
 
 
  ; Eventloop
  Repeat 
  	Define event=WaitWindowEvent()
  	If event=#PB_Event_Gadget And EventGadget()=0
  		Debug "button Press"
  		StopSuperviseDirectory("F:\Testcopy\test")
                ; hier könnte dann auch ein neues Verzeichnis zur Überwachung erstellt werden
    EndIf 
  	
  Until  event = #PB_Event_CloseWindow
 
  ; Stop SuperVisorDirectory
  StopSuperviseDirectory("F:\Testcopy\test")
 
CompilerEndIf
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Ordner Überwachung

Beitrag von Bisonte »

Hallo Bisnote,
n und o vertauschen ;)

Habe das genauer angesehen, und muss tatsächlich feststellen, dass da eigenartige Programmabrüche passierten, wenn StopSuperviseDirectory()
benutzt wurde. Da liegt es an dem ReadDirectoryChangesW_(), weil es innerhalb des Threads ja darauf wartet, dass etwas passiert.
Da blieb eigentlich nur die Radikalkur und der Thread wird jetzt per KillThread() abgeschossen.

Habe im Thread: SuperviseDirectory() & GetKnownFolder() [Module][WIN] den Code angepasst.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: Ordner Überwachung

Beitrag von silbersurfer »

Danke Bisonte,
werde es gleich probieren, denn es ist in mein Filmanger Projekt notwendig diese Dynamisch zu starten und zu beenden.
das Problem liegt an dem Menagment von Windows, sobald die überwachung nicht korekt abgeschlossen ist (beendet wurde)
ist das besagte Verzeichnis quasi schreibgeschützt.
Man kann es nicht löschen oder umbennen, das es möglich ist sieht man am Totalcomannder und Co.
irgendetwas feht also. auch TS-Soft Projekt JAComannder hat den besagten Fehler, ich gehe davon aus das er es auch über die im diesen Thread besproche Variante
gemacht hat

Edit: Hallo Bisonte,
leider ist das Problem damit nicht gelöst die Überwachung bleibt nach wie vor Activ
KillThread bricht zwar deinen Thread ab, lasst aber den von ReadDirectoryChangesW_() überwachten Ordner Activ
somit kann man diesen nicht löschen oder ändern.

Gruss Silbersurfer
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Ordner Überwachung

Beitrag von Bisonte »

Jetzt, nachdem ich Stunden damit zugebracht habe, eine offizielle "Abbruchmethode" im Netz zu finden...

Meine Strategie, ReadDirectoryChangesW so abzubrechen, wie ich es in meinem Modul mache, scheint komplett falsch zu sein.

Das RDCW blockt sozusagen selbst. Das wird schwieriger zu beheben als gedacht. Aber ich suche noch ;)
Also das Modul ist jetzt momentan nichts für dich, wegen mangelnder Abbruchmöglichkeit.

Es war eigentlich ursprünglich gar nicht dafür gedacht... es sollte nur ein oder mehrere Ordner überwacht werden. Das stoppen
der Überwachung war bisher eigentlich nicht wirklich nötig. (Programmende immer sauber erreicht)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Ordner Überwachung

Beitrag von ts-soft »

auch TS-Soft Projekt JAComannder hat den besagten Fehler,
Kann ich mir nicht vorstellen :mrgreen:
Oder bekommt man den auch ohne Threads?
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
silbersurfer
Beiträge: 174
Registriert: 06.07.2014 12:21

Re: Ordner Überwachung

Beitrag von silbersurfer »

@Bisonte
Es war eigentlich ursprünglich gar nicht dafür gedacht...
das hatte ich dir schon damals aufgezeigt, das dein Thread nicht sauber beendet wird
Siehe hier: viewtopic.php?f=16&t=30754
freut mich aber das du nach einer lösung suchst, da es um einiges schneller wäre nur die Datein zu änder die sich auch nur geändert haben :-)

@ts-soft
Kann ich mir nicht vorstellen :mrgreen:
oh ja, da du ja on Fly die Überwachung änderst.
Ich habe den gleichen Fehler bei deinen Jacomannder gefunden, teste es selber (erstelle ein Verzeichnis, gehe dann in das Verzeichnis und wieder raus, und lösche es dann)
du wirst wie ich den gleichen Fehler gemacht haben

Code: Alles auswählen

Procedure FolderSpy(*SLook.Look)
	Protected exit.l,dummyObjekt.l=hchangeobject.l
	While exit = 0	
		hchangeobject=FindFirstChangeNotification_(*SLook\Directory,0,1)	
		If WaitForSingleObject_(hchangeobject,*SLook\Milliseconds)=0
		Debug "etwas passiert hier !"
		If *slook\stop
			Debug "Thread Beendet"
			Break
		Else 
			 FindNextChangeNotification_(hchangeobject)
		EndIf 	
	Wend
EndProcedure
richtig wäre aber es so gewesen

Code: Alles auswählen

Procedure FolderSpy(*SLook.Look)
	Protected exit.l,dummyObjekt.l=hchangeobject.l
	hchangeobject=FindFirstChangeNotification_(*SLook\Directory,0,1)	
	While exit = 0	
		If WaitForSingleObject_(hchangeobject,*SLook\Milliseconds)=0
		Debug "etwas passiert hier !"
		If *slook\stop
			Debug "Thread Beendet"
			Break
		Else 
			 FindNextChangeNotification_(hchangeobject)
		EndIf 	
	Wend
EndProcedure
egal ob mit oder Ohne Thread das Ergebnis bleibt das selbe, der Fehler liegt im Detail
die Zeile
hchangeobject=FindFirstChangeNotification_(*SLook\Directory,0,1)
darf auf keinen Fall in der schleife liegen, da diese einen nuene Thread startet, was das beenden verhindert.
Jetzt läuft es bei nir so wie gedacht.

gruss
Silbersurfer
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Antworten