Moin,
ich habe mir mal ein Programm geschrieben was ein vom benutzer eingestelltes Verzeichnis überwacht und bei Änderungen darin überprüft ob alle Dateien darin i.O. sind. Das wird mit Hilfe eines Threads gemacht.
Delphi-Quellcode:
procedure TcsDirThread.Execute;
var
pBuf : Pointer;
dwBufLen : DWORD;
dwRead : DWORD;
FNI : FILE_NOTIFY_INFORMATION;
pWork : Pointer;
sFileName : Widestring;
dwWaitStatus : DWORD;
begin
FhFile := CreateFile(PChar(FsDirPath),
FILE_LIST_DIRECTORY or GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,0);
hNotifity := FindFirstChangeNotification(PChar(FsDirPath), //Verzeichnis
false, //unterverzeichnisse überwachen
FILE_NOTIFY_CHANGE_FILE_NAME or
FILE_NOTIFY_CHANGE_LAST_WRITE or
FILE_NOTIFY_CHANGE_SIZE or
FILE_ACTION_ADDED or
FILE_ACTION_REMOVED or
FILE_ACTION_MODIFIED);
if (FhFile = INVALID_HANDLE_VALUE) or (FhFile = 0) then
begin
RaiseLastWin32Error;
Terminate;
end;
if (hNotifity = INVALID_HANDLE_VALUE) then
begin
RaiseLastWin32Error;
Terminate;
end;
dwBufLen := 65536;
pBuf := AllocMem(dwBufLen);
try
while ((FindNextChangeNotification(hNotifity)) and (not terminated)) do
begin
Synchronize(Application.ProcessMessages);
dwWaitStatus := WaitForSingleObject(hNotifity, 1000);
if (dwWaitStatus = WAIT_FAILED) then
begin
RaiseLastWin32Error;
Terminate;
end;
if (dwWaitStatus = WAIT_OBJECT_0) then
begin
ReadDirectoryChangesW(FhFile,pBuf,dwBufLen,true,
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 or
FILE_ACTION_ADDED or
FILE_ACTION_REMOVED or
FILE_ACTION_MODIFIED,
@dwRead,nil,nil);
pWork := pBuf;
repeat
StrMove(@FNI,pWork,12);
PChar(pWork) := PChar(pWork)+12;
sFileName := StringOfChar(#00,FNI.dwFileNameLength);
StrMove(@sFileName[1],pWork,FNI.dwFileNameLength);
FsFileName := WideCharToString(PWideChar(sFileName));
FsFileName := copy(FsFileName,1,length(FsFileName) shl 1);
FsReason := GetReason(FNI.dwAction);
Synchronize(AddFileToList);
PChar(pWork) := PChar(pBuf)+FNI.dwNextEntryOffset;
until FNI.dwNextEntryOffset = 0;
end;
end;
if (LowerCase(ExtractFileExt(FsFileName)) = '.bmp') then
begin
PostMessage(MainForm.Handle, Verzeichnisaenderung_bmp, 0, ProjektID);
end;
finally
FreeMem(pBuf,dwBufLen);
end;
end;
Jetzt habe ich mal eine neuen Datei angelegt und wieder gelöscht dann ist das alles kein Problem. Die Änderungen wird mit AddFileToList in eine TStringList eingefügt und kann bei bedarf angezeigt ode gespeichert werden. Anschließend habe ich mal mit TotalCommander das Dateidatum geändert und wollte mir dann mal die StringList angucken. Da trat mein Problem auf: In meiner StringList waren fast 500000 einträge. Das Speichern der Datei war möglich, dauerte natürlich sehr lange und die Datei war anchher 142 MB groß (reine Textdatei), aber das Anzeigen der StringList in TListBox mit Assign ging gar nicht mehr. Nachdem die Auslagerungsdatei auf 1,94 GB erweitert wurde, wollte mein Rechner nicht mehr.
Warum sind da sol viele Änderungen drin. Das lustige dabei ist das bis auf die ersten 2 Änderungen (Datei anlegen und löschen) immer das selbst stand (Datei wurde geändert). Immer wieder das selbe. Im Abstand von weniger als 1 sekunde. Ist das jetzt ein Problem bei mir oder ein Problem von Windows das ich umgehen muss? Wäre nett wenn ihr mir Tipps und Anregungen geben würdet.