![]() |
Re: Festplattenzugriffe
Zitat:
ich weis dass du das wohl nicht mehr brauchst aber ich habe 2 interessante Dinge gefunden die dich vlt. (doch) noch interessieren zu deinem damaligen Problem: ![]() Und aus der MSDN: Zitat:
![]() |
Re: Festplattenzugriffe
Das ERROR_INVALID_PARAMETER könnte ein Problem erklären ... ich laß inzwischen den entsprechenden Thread mit erhöhter Priorität laufen und schon geht es, nur kommt jetzt hinzu, daß man nur den Datei-/Verzeichnisnamen bekommt, was bei WatchSubtree=True zu problemen führt, man erfährt leider nicht wo in dem ganzen Verzeichnisbaum die Datei liegt.
Da darf man ja dennoch alles durchsuchen und eindeutiger wird es erst recht nicht, wenn mehrere Dateien mit dem selben Namen existieren. Praktisch könnte man jetzt zwar für jedes Unterverzeichnis einzeln eine Überwachung einrichten, nur könnte man dann keine Verzeichnisse mehr löschen, da diese ja geöffnet wären. (abgesehen von den Unmassen an Handles und Überwachungsthreads) Und wenn man eh alles durchsuchen muß, wäre diese ReadDirectoryChangesW doch schon fast nurtzlos. Zu "Eric Gunnerson's C# Compendium" schön daß man jetzt anscheinend auch noch auf die kurzen Dateinamen achten muß :wall: |
Re: Festplattenzugriffe
Liste der Anhänge anzeigen (Anzahl: 1)
Moin Zusammen,
ich habe hier mal ein Demoprojekt für die asynchrone Verwendung von ReadDirectoryChangesW angehängt. Das Projekt ist (wie ich denke ;-)) vollständig dokumentiert. Zwei Punkte noch vorab, auch wenn sie bereits in der Dokumentation stehen:
Suchbegriffe, damit in der Demo enthaltene Begriffe über die Suche gefunden werden können: ReadDirectoryChangesW, CreateIoCompletionPort, GetQueuedCompletionStatus, FILE_NOTIFY_INFORMATION, OVERLAPPED, WC_NO_BEST_FIT_CHARS, FILE_LIST_DIRECTORY [EDIT] Fehler in Demo korrigiert [/EDIT] [EDIT2] Demo erneut korriert :oops: [/EDIT2] |
Re: Festplattenzugriffe
Hallo Christian,
vielen Dank fuer das Demo. Musst nur in der Zeile 193
Delphi-Quellcode:
den Backslash rausmachen da man sonst Sachen wie C:\\xxxxx bekommt.
FsResult := FsPath + '\' + FsResult;
Und warum sind im Memo hinter den FileNames immer "???"? |
Re: Festplattenzugriffe
Schau dir mal die windows-registry an, wie viele doppelte backslashes du da drin hast :roll:
das hinzufügen des backslash ist sehr viel einfacher als es durch IncludeTrailingPathDelimiter zu jagen. |
Re: Festplattenzugriffe
Zitat:
|
Re: Festplattenzugriffe
Moin Mackhack,
woher die ??? kommen kann ich mir im Moment auch nicht erklären, denn bei mir treten sie nicht auf. Kannst Du mal ein Beispiel dafür angeben, was Du überwacht hast und mit welchem NotifyFilter? Ausserdem könnte noch das Betriebssystem wichtig sein. Den zusätzlichen Backslash hast Du übrigens nur, wenn Du ein Laufwerk angibst. Wenn Du ein Verzeichnis nimmst, tritt das nicht auf. Für Windows spielt übrigens die Anzahl aufeinanderfolgender Pfadtrennzeichen keine Rolle, sie werden immer als einer gewertet. |
Re: Festplattenzugriffe
Hi,
also hier mal die Daten und ein Beispielauszug aus dem Memo. Windows XP Media Center Edition English SP2 Filter: FILE_NOTIFY_CHANGE_LAST_WRITE Ueberwachung: C:\ File aus Memo: C:\\Documents and Settings\{USERNAME}\Application Data\{ANWENDUNG}\{ANWENDUNG}.statistics.bak???? |
Re: Festplattenzugriffe
Moin Mackhack,
ich glaube ich habe den Fehler gefunden: Ein SetLength steht an der falschen Stelle
Delphi-Quellcode:
So 'was Blödes :wall:
// Falsch
if iLen = 0 then begin FsResult := 'ERROR'; end else begin FsResult := FsPath + '\' + FsResult; SetLength(FsResult,iLen); end; // Richtig if iLen = 0 then begin FsResult := 'ERROR'; end else begin SetLength(FsResult,iLen); FsResult := FsPath + '\' + FsResult; end; Ausserdem habe ich noch etwas gefunden: Da der Dateiname in der Struktur FILE_NOTIFY_INFORMATION (wFilename) ja vom Typ WChar ist, kann die Längenangabe verkleinert werden:
Delphi-Quellcode:
FILE_NOTIFY_INFORMATION = packed record
dwNextEntryOffset : DWORD; dwAction : DWORD; dwFileNameLength : DWORD; wFilename : array [1.._iFilenameLength shr 1] of WCHAR; // shr 1 ist neu end; [EDIT] Korrgierte Demo hochgeladen BUG: SetLength in der falschen Zeile BUG: Länge von wFilename in FILE_NOTIFY_INFORMATION [/EDIT] [EDIT2] Demo erneut korriert :oops: BUG: Man sollte auch den Buffer für das Ergebnis (FNI) initialisieren :wall: BUG: Länge von wFilename in FILE_NOTIFY_INFORMATION. Wenn ich durch 2 teilen will sollte ich wohl besser nicht shr 2 nehmen :wall: [/EDIT2] |
Re: Festplattenzugriffe
Zitat:
//Edit: Darf ich dich hier mal noch fragen was ich dich bereits in meiner PM fragte? Warum musst du hier das Struct (Record) ![]() ![]() Das ist etwas im allgemeinen das ich noch nie im Zusammenhang mit der MSDN/API verstanden habe wann ich ein Struct deklarieren muss und wann nicht. Gibt dafuer n einfaches Hint fuer mich und vlt. auch fuer viele/einige andere hier? |
Re: Festplattenzugriffe
Moin Mackhack,
ich habe einmal die Konstante _iFilenameLength angelegt, da diese in der Hauptroutine, als Anzahl Bytes die maximal kopiert werden dürfen, so benötigt wird. Da das Array aber nur halb soviele Elemente braucht (WChar ist zwei Byte gross), teile ich an der Stelle den Wert durch 2. SHR ist zwar zum rechnen da, aber das passiert da ja auch ;-) Da beide Werte konstant sind (_iFilenameLength und natürlich die 1) wird dies schon beim compilieren erledigt. |
Re: Festplattenzugriffe
Kann mir jemand meine Fragen vom Edit vlt. bitte beantworten. Das laege mir sehr am Herzen das mal zu verstehen...
Vielen Dank! |
Re: Festplattenzugriffe
Moin Mackhack,
Zitat:
FILE_NOTIFY_INFORMATION musste ich selber deklarieren, da diese Deklaration bei Delphi nicht mitgeliefert wurde, OVERLAPPED hingegen schon (unit Windows). Zitat:
Im Allgemeinen wirst Du oft Funktionen / Strukturen selber deklarieren müssen, die es nur unter NT/2000/XP gibt, nicht aber unter 9x/ME, da diese meist nicht vordeklariert sind. Warum jetzt ReadDirectoryChangesW deklariert wurde, nicht aber die hierfür benötigte Struktur FILE_NOTIFY_INFORMATION müsstest Du bei Borland anfragen (zumindest konnte ich die Deklaration nirgends finden, auch nicht in D2006). Manche Sachen, die sonst fehlen kannst Du auch woanders finden (vieles z.B. in den Jedis), aber ich verwende da lieber eigene Deklarationen (bei Funktionen), um die Funktionen C-typisch deklariert zu bekommen, also ohne var-Parameter, weil ich es damit leichter habe Beispiele umzusetzen, und mir auch keine Gedanken darum machen muss, ob das mit einem var-Parameter überhaupt wie gewünscht funktioniert (siehe ExtractIconEx). |
Re: Festplattenzugriffe
Hallo Christian,
vielen Dank fuer die Erklaerung. Sieht alles schon wesentlich besser aus jetzt :-) |
Re: Festplattenzugriffe
Liste der Anhänge anzeigen (Anzahl: 1)
Also, der Hauptgrund, warum FindFirstChangeNotificationW und ReadDirectoryChangesW zusammen war, lag darin, daß es in dem Code welcher als Vorlage dafür diehnte auch so war.
Und da ReadDirectoryChangesW in dieser Verbindung immer darauf wartet, bis etwas passiert und nicht vorher zurückkehrt (man es also auch nicht beenden konnte), hielt mich natürlich davon ab dieses FindFirstChangeNotificationW zu entfernen, da dort über WaitForSingleObject durch dem Timeout ein Abbruch möglich war ._. Deshalb wird auch nur wenn etwas da ist (also WaitForSingleObject = WAIT_OBJECT_0) ReadDirectoryChangesW aufgerufen. Hab inzwischen auch bemerkt, daß bei dir statt dessen CreateIoCompletionPort verwendet wird und ReadDirectoryChangesW wartet nicht, wenn nichts vorhanden ist. Find*ChangeNotificationW+WaitForSingleObject und CreateIoCompletionPort sind doch aber "nur" unterschiedliche Methoden, um auf ein Ereignis zu warten. Da frag ich mich nun aber warum dann ReadDirectoryChangesW unterschiedlich reagiert. :gruebel: mit Find*ChangeNotificationW+WaitForSingleObject: -wartet bis zu einem Ereignis (1) -liefert nur den Dateinamen und kein Verzeichnis -liefert nur das letzte Ereignis -manchmal liefert es garnichts und warte auf das nächste Ereignis. mit CreateIoCompletionPort: -kehrt immer sofort wieder zurück (1) -liefert den kompletten Pfad (1) inwischen geklärt, dat kommt wohl durchs Overlapt. Zitat:
PS: ich seh nichts doppelt. (zum Test 'ne Datei umbenannt) Zitat:
(FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or FILE_NOTIFY_CHANGE_LAST_WRITE or FILE_NOTIFY_CHANGE_CREATION) Zitat:
Eventuell liefert das ja eine mögliche Antwort ^^ Zitat:
|
Re: Festplattenzugriffe
Moin Himitsu,
Zitat:
Zitat:
[EDIT] Zitat:
Zitat:
[/EDIT] |
Re: Festplattenzugriffe
Zitat:
Also erst mit irgendwas anderem prüfen ob es überhaupt was gibt und nur wenn was vorhanden ist, dann dieses abfragen :angel2: Zitat:
Is aber erstmal raus, ohne und asynchron läuft es ja auch ganz nett ^^ Zitat:
|
Re: Festplattenzugriffe
Moin Himitsu,
Zitat:
|
Re: Festplattenzugriffe
Na das würde auch eines der Probleme damit erklären, aber die Idee stammt zum Glück nicht von mir und wandert dennoch fröhlich um die Welt :stupid:
![]() |
Re: Festplattenzugriffe
Moin Himitsu,
da es bei den beiden Suchbegriffen reichlich Fundstellen gibt: Welche Site meinst Du? |
Re: Festplattenzugriffe
Es war eine von den ersten 10 :roll:
Welche Seite es war weiß ich nicht mehr genau, vorallem da ich dort über andere Suchbegriffe hingekommen bin ('s wär jetzt ä bissl viel mir nochmal alle anzusehen, nur um die Eine wiederzufinden) War mehr als Beispiel ... ich denke mal ganz einfach, daß es darunter massenhaft Seiten gibt, wo die beiden Funktionen auch zusammen verwendet werden :angel2: (wenn ich Glück hab, liegt noch eine Kopie der Seite daheim im Papierkorb) |
Re: Festplattenzugriffe
Ähhh ja ... gefunden hatt'sch nichts mehr.
Und Google spuckt irgendwie ständig was anderes aus, nur nicht die Seite mit dem Code. :gruebel: Zitat:
Nach meinen Beobachtungen sind wohl 2*SizeOf(FILE_NOTIFY_INFORMATION) [1064 Bytes], also schöne 2 KB völlig ausreichend. [size=1]PS: 64 KB = Windows-Speicherseite[/size] FILE_NOTIFY_CHANGE_LAST_ACCESS: Hierzu nur 'ne Empfhelung, da dieses oftmal in den Codes da oben auftaucht. Wählt die zu überwachenden Ereignisse mit bedacht, denn wenn man Dateiänderungen überwachen möchte, dann ist der Lesezugriff irgendeines Programmes uninteressant. :zwinker: @Luckie, zwecks "Zugriff verweigert" #23: ich löse das inzwischen so, daß der Überwachungsthread seine Ereignisse nur in ein Array einträgt (incl. Zeit) und erst dann zeitversetzt in einem anderem Thread ausgewertet wird. Für Langzeitüberwachungen (ohne sofortige Auswertung) sollte es sich über ![]() > ![]() ![]() Was diese süße "12-Byte"-Temp-Variable (FNI) angeht, welche hier oftmals verwendet wird ... wie wäre es, wenn man einfach nur nach PFileNotifiInformation castet? :zwinker: z.B.: PFileNotifiInformation(P)^.Action |
Re: Festplattenzugriffe
Zitat:
|
Re: Festplattenzugriffe
Na ja, Windows verwaltet ja "praktischer" Weise (aus seiner Sicht) den Speicher in 64-KB-Blöcken.
Und da die netten Lese-/Schreibzugriff immer Blockweise durchgeführt werden, ist es nunmal besser sich gleich an diesen Blockgrößen auszurichten. Und da es ja mehrere Speicher/Zwischenspeicher gibt, welche zusammen arbeiten (hintereinander liegen), ist es wohl besser sich an den größten Speicherblock zu halten. Und hab bei mir derzeit 'ne durchschnittliche Blockgröße von maximal 512 KB (min. 128 KB) ausfindig bemacht. Daten auslesen/ändern auf NTFS und FAT32. Ist halt ein Wert, welcher wo es durchschnittlich am Schnellsten ging. PS: das NTFS nicht gerade schnell ist, war mir leider schon bewußt -.-'' [add] Im Grunde wollte ich ja nur sagen, daß es einfach (im Durchschnitt) besser ist, wenn man sich möglichst am größten Speicherbereich, welcher von an verschiedensten Stellen herumgeschoben wird orientiert, wenn man seinen eigenen Zwischenspeicher dimensioniert. Sektorgröße, Clustergröße, Festplattencache, WindowsFileCache... Wobei es da schon genug leicht auszulesende Größen gibt und nicht unbedingt alles ermittelt werden muß. (Wie NTFS intern funktioniert hab ich noch nicht durch ... hänge derzeit noch an FAT ._.) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:09 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz