Seite 3 von 4

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 10.03.2018 11:24
von Sicro
Bisonte hat geschrieben:

Code: Alles auswählen

FileAction_File = PeekS(@buffer\Filename, buffer\FileNameLength, #PB_Unicode)
Das ist auch nicht korrekt, weil PeekS() als Parameterangabe die Anzahl der Zeichen haben möchte, die ausgelesen werden sollen, buffer\FileNameLength enthält aber laut MSDN (FILE_NOTIFY_INFORMATION) die Länge des Dateinamens in Bytes.
Deine Zeile sollte also so aussehen:

Code: Alles auswählen

FileAction_File = PeekS(@buffer\Filename, buffer\FileNameLength / 2, #PB_Unicode)
Ein Unicode-Zeichen in PB benötigt 2 Bytes.

Der Grund, warum du den Fehler nicht reproduzieren kannst, liegt daran, weil bei deinem buffer\Filename glücklicherweise jedes Mal ein Null-Byte am Ende ist und PeekS() rechtzeitig mit dem Auslesen abbricht. Die Parameterangabe "Länge" bei PeekS() gibt ja nur die maximale Anzahl zu lesende Zeichen an, wenn aber schon vorher ein Null-Byte entdeckt wird, bricht PeekS() schon vorher mit dem Auslesen ab. Im buffer\Filename von oO0XX0Oo gibt es aktuell leider erst viel später ein Null-Byte, weshalb nach dem Dateiname auch noch weitere Zeichen aus dem Memory gelesen werden.

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 10.03.2018 14:05
von Bisonte
Hab ich das Bytes überlesen ? Alle Achtung.
Dann macht das ganze natürlich Sinn.

Änderung wird implementiert.

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 11.03.2018 18:24
von oO0XX0Oo
Danke @Sicro für die Erklärung und die Korrektur der nötigen Zeile und danke @Bisonte
für die Änderung(en)!

Funktioniert hier im Moment hervorragend :mrgreen:

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 05.08.2018 12:00
von Bisonte
Neues Update : V1.06

Das beenden einer Überwachung ist wohl etwas buggy gewesen. Da innerhalb des Threads ReadDirectoryChangesW die Bremse darstellt,
blieb nur ein Killthread übrig. Dank an Silbersurfer fürs entdecken.

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 11.05.2022 21:14
von Regenduft
Anscheinend hatte ich mich beim Suchen im Forum vertippt... sonst hätte ich nicht das Rad neu erfinden müssen.. :roll:

Mir ist bei Deinem Code ein potentieller Fehler aufgefallen - eventuell liege ich aber falsch und meine (sehr ähnliche) Lösung ist fehlerhaft...

Dein Code:

Code: Alles auswählen

If SHGetKnownFolderPath(*FolderID, kfFlag, #Null, @*UnicodeBuffer) = #S_OK And *UnicodeBuffer
  Result = PeekS(*UnicodeBuffer, -1, #PB_Unicode) + "\"
  CoTaskMemFree_(*UnicodeBuffer)
EndIf
Mein Code:

Code: Alles auswählen

Define *Path, *ppszPath.String = @*Path

If SHGetKnownFolderPath(*rfid, KF_Flags, 0, *ppszPath ) >= 0 And *Path And Asc(*ppszPath\s)
  Result$ = *ppszPath\s + "\"
EndIf

CoTaskMemFree_(*Path)
*Path = 0
Ich rufe CoTaskMemFree_() IMMER auf, denn...
https://docs.microsoft.com/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath hat geschrieben:
Type: PWSTR*

When this method returns, contains the address of a pointer to a null-terminated Unicode string that specifies the path of the known folder. The calling process is responsible for freeing this resource once it is no longer needed by calling CoTaskMemFree, whether SHGetKnownFolderPath succeeds or not. The returned path does not include a trailing backslash. For example, "C:\Users" is returned rather than "C:\Users\".
Ein Aufruf von CoTaskMemFree_() mit einem Null-Zeiger ist übrigens keine Problem:
https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree hat geschrieben:[in, optional] pv

A pointer to the memory block to be freed. If this parameter is NULL, the function has no effect.
Ansonsten überprüfe ich noch mit "Asc(*ppszPath\s)", dass SHGetKnownFolderPath() nicht einen Leerstring rückgegeben hat, bevor ich "\" anhänge.

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 12.05.2022 09:12
von Bisonte
@Regenduft: Ok ... guter Einwand ;)

Die Reihenfolge ist auch so im Original, daher hab ich das so übernommen.
Es macht für mich Sinn, nur wenn SH auch was zurückgibt, das wieder freizugeben...
Allerdings ist deine Begründung stichhaltig ( von wegen es ist egal ob NULL oder nicht bei CoTaskMemFree ) ;)

Das Überprüfen auf Leerstring ist allerdings eine Sache die ich anscheinend übersehen habe...
wobei dieser Fall bisher noch nie eintrat, oder sich nicht bemerkbar machte.
(Dafür hatte ich ja extra die Konstanten gewählt... und weil man sich das leichter merken kann ;)

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 20.11.2022 21:09
von oO0XX0Oo
Ich hab gerade noch mal zwei Fragen:

01.
Was ist denn der Grund dafür, dass eine Datei, die geändert wird, 2 mal vom superviser thread gefunden wird?

Also ich überwache z.B.: "D:\Temp"

Dort liegt die Datei "___a.txt"

Jedesmal, wenn ich die Datei editiere und dann wieder speichere:

File ___a.txt was modified
File ___a.txt was modified

Kann man das auch auf 1 x begrenzen (also ohne das man jetzt schauen würde ob die letzte entdeckte Datei wieder der jetztigen entspricht) :)


02. Gibt es einen Grund, warum das supervising nicht für UNC Pfade funktioniert?

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 21.11.2022 01:59
von Bisonte
oO0XX0Oo hat geschrieben: 20.11.2022 21:09 Ich hab gerade noch mal zwei Fragen:

01.
Was ist denn der Grund dafür, dass eine Datei, die geändert wird, 2 mal vom superviser thread gefunden wird?

Also ich überwache z.B.: "D:\Temp"

Dort liegt die Datei "___a.txt"

Jedesmal, wenn ich die Datei editiere und dann wieder speichere:

File ___a.txt was modified
File ___a.txt was modified

Kann man das auch auf 1 x begrenzen (also ohne das man jetzt schauen würde ob die letzte entdeckte Datei wieder der jetztigen entspricht) :)


02. Gibt es einen Grund, warum das supervising nicht für UNC Pfade funktioniert?
Zu 1: Ja, das kann man begrenzen.

MSDN Link : https://learn.microsoft.com/en-us/windo ... rychangesw

In der Threadprozedur wir der NotifyFilter mit #FILE_NOTIFY_CHANGE_ALL definiert. in der MSDN stehen diverse Werte, wie du es anpassen kannst, das nur bestimmte Ereignisse erfasst werden.
In meinem "original" reagiert er 2x weil einmal ein Speichern (also Attribute z.b. Datumstempel) geändert wird UND die Dateigrösse sich ändert...

und zu 2... Ich schätze es liegt daran, dass die Funktion ReadDirectoryChanges für Windows XP geschrieben wurde, wo es so etwas noch nicht gab... bzw keiner an sowas gedacht hat. Also zu alt ;)
Eine wirkliche Antwort weiss ich darauf nicht....

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 21.11.2022 09:52
von oO0XX0Oo
Hi Bisonte und danke für deine Antwort.

1. Auch wenn ich

Code: Alles auswählen

Protected NotifyFilter.l = #FILE_NOTIFY_CHANGE_LAST_WRITE
benutze (oder alternativ zum Testen: #FILE_NOTIFY_CHANGE_SIZE)

bekomme ich trotzdem immer 2 events beim Speichern der Datei...

2. Eigentlich sollte das gehen:
ReadDirectoryChangesW fails with ERROR_INVALID_PARAMETER when the buffer length is greater than 64 KB and the application is monitoring a directory over the network. This is due to a packet size limitation with the underlying file sharing protocols.
Es wäre auch komisch, wenn das nicht so wäre. XP kam erst nach Windows 2000 heraus und 2000 wurde damals schon in Firmennetzwerken verwendet wo es fileserver mit Freigaben gab.

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Verfasst: 22.11.2022 23:40
von oO0XX0Oo
Hätte irgendjemand Zeit, sich das (noch mal) anzuschauen, warum es trotz Limitierung auf #FILE_NOTIFY_CHANGE_LAST_WRITE oder #FILE_NOTIFY_CHANGE_SIZE immer 2 events auswirft und warum es zur Zeit nicht mit UNC-Pfaden funktioniert?

Ich geb auch gern ein Bier oder 2 dafür aus ;)