ReadDirectoryChangesW raff ich nicht...
-
Hallo zusammen,
ich hab ein Problem mit dem Einsatz von ReadDirectoryChangesW. Ich muß dazu anmerken, dass ich aus der BCB-Fraktion stamme und so weit als möglich immer einen großen Bogen um die WinAPI gemacht habe... Erklärungen also bitte für Dummies.
Folgendes habe ich mir aus diversen Quellen zusammengefrickelt und läuft in einem (Borland-spezifischen) Thread:
Header:
class TWatchThread : public TThread { private: int Counter; HANDLE FDirectoryHandle; DWORD FBytesWritten, FNotifyFilter, bufsize; FILE_NOTIFY_INFORMATION FNotificationBuffer; TOverlapped FOverlapped; char* fInfo; void __fastcall EventFired(void); AnsiString asFileName; protected: void __fastcall Execute(); public: __fastcall TWatchThread(bool CreateSuspended); };CPP:
__fastcall TWatchThread::TWatchThread(bool CreateSuspended) : TThread(CreateSuspended) { FDirectoryHandle = 0; ZeroMemory(&FOverlapped, sizeof(FOverlapped)); bufsize = sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(wchar_t); fInfo = new char[FBytesWritten]; } void __fastcall TWatchThread::Execute() { Counter = 0; AnsiString asPath = "c:\\scanner"; FNotifyFilter = FILE_NOTIFY_CHANGE_LAST_WRITE; FDirectoryHandle = CreateFile(asPath.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0); if (FDirectoryHandle == INVALID_HANDLE_VALUE) { FDirectoryHandle = 0; ShowMessage(SysErrorMessage(GetLastError())); Terminate(); } while (!Terminated) { ZeroMemory(&FNotificationBuffer, sizeof(FNotificationBuffer)); ZeroMemory(fInfo, FBytesWritten); ReadDirectoryChangesW(FDirectoryHandle, fInfo, bufsize, false, FNotifyFilter, &FBytesWritten, &FOverlapped, NULL); if(WaitForSingleObject(FDirectoryHandle, 1000) == WAIT_OBJECT_0) { ++Counter; // asFileName = AnsiString(((FILE_NOTIFY_INFORMATION*) fInfo)->FileName); Synchronize(EventFired); } } if (FDirectoryHandle) CloseHandle(FDirectoryHandle); // delete[] fInfo; }Das läuft so prinzipiell...
Allerdings verstehe ich nicht, wozu FOverlapped gut sein soll. Ohne funktioniert es jedoch nicht (auch wenn ich FILE_FLAG_OVERLAPPED bei der Erzeugung des Directory Handles weglasse.). MSDN und SDK-Hilfe haben nur noch mehr Fragen aufgeworfen... Brauch ich das FOverlapped wirklich? Wenn ja, wofür? Wenn nicht, wie krieg ich es weg?
Das mit der bufsize habe ich hier aus einem Beitrag von Flenders. Verstehen tu ich es nicht, da ja mehrere Dateien in einer FILE_NOTIFY_INFORMATION Struktur stehen können. Muß ich da einfach sicher stellen, dass genügend Speicher reserviert ist, oder hat es einen tieferen Sinn, warum die bufsize so ermittelt wird?
Das Ergebnis ist fast richtig, aber das Ende des Dateinamens wird nicht korrekt erkannt. Es ist immer mindestens ein Zeichen zuviel. Im wchar_t FileName steht z.B. 'test.txt/x7865'. Muß ich zwangsläufig FILE_NOTIFY_INFORMATION::FileNameLength verwenden?
Wie komme ich an einen möglichen zweiten Dateinamen in der Struktur? Einfach einen weiteren Zeiger erstellen und den FILE_NOTIFY_INFORMATION::NextEntryOffset hinzuaddieren?Schon mal vielen Dank im voraus.
-
Ok, dass ich den Dateinamen nicht korrekt auslesen konnte, war ein dummer Fehler. Ich hab beim letzten Umstricken vergessen die Zeilen 8 und 32 zu ändern. Dort gehört natürlich bufsize und nicht FBytesWritten hin.
fInfo = new char[bufsize]; ZeroMemory(fInfo, bufsize);Dafür hab ich jetzt noch festgestellt, dass der Event teilweise mehrfach gefeuert wird? Ist das normal?
-
Keine Antwort ist auch eine Antwort... Da es auch keine Kommentare oder Nachfragen gegeben hat, kann ich davon ausgehen, dass hier einfach die Kompetenz fehlt?
-
nimm doch was fertiges: http://www.codeproject.com/file/directorychangewatcher.asp