(Co-Admin)
Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
Delphi 11 Alexandria
|
Re: Festplattenzugriffe
8. Mär 2006, 21:27
Moin Luckie,
vielleicht klappt es asynchron besser.
Hier mal ein, leicht zusammengestrichenes Beispiel (was Du für Deinen Zweck wohl auch noch umsortieren müsstest:
Delphi-Quellcode:
const
_iFilenameLength = MAX_PATH*2;
type
PFILE_NOTIFY_INFORMATION = ^FILE_NOTIFY_INFORMATION;
FILE_NOTIFY_INFORMATION = packed record
dwNextEntryOffset : DWORD;
dwAction : DWORD;
dwFileNameLength : DWORD;
wFilename : array [1.._iFilenameLength] of WCHAR;
end;
var
pBuf : Pointer;
pWork : Pointer;
dwBufLen : DWORD;
dwDummy : DWORD;
sResult : string;
FNI : FILE_NOTIFY_INFORMATION;
dwRead : DWORD;
dwKey : DWORD;
pOVL : POVERLAPPED;
iCopyLen : integer; // Prevent Buffer Overflow
begin
// Normalerweise im Konstruktor erzeugt
FhDir := CreateFile(PChar(FsPath),FILE_LIST_DIRECTORY,FILE_SHARE_READ or FILE_SHARE_DELETE or FILE_SHARE_WRITE,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED,0);
FhComPort := CreateIoCompletionPort(FhDir,0,$1234ABCD,0);
FillChar(Fovl,SizeOf(Fovl),0);
// Execute
pOVL := @Fovl;
dwBufLen := 65536;
GetMem(pBuf,dwBufLen);
try
while not Terminated do begin
ZeroMemory(pBuf,dwBufLen);
if not ReadDirectoryChangesW(FhDir,pBuf,dwBufLen,true,FILE_NOTIFY_CHANGE_LAST_WRITE,@dwDummy,@Fovl,nil) then Terminate;
if Terminated then break;
if not GetQueuedCompletionStatus(FhComPort,dwRead,dwKey,pOVL,INFINITE) then begin
Terminate;
end else begin
if Terminated then break;
pWork := pBuf;
repeat
CopyMemory(@FNI,pWork,12);
iCopyLen := FNI.dwFileNameLength;
if iCopyLen > _iFilenameLength then iCopyLen := _iFilenameLength;
CopyMemory(@FNI.wFilename[1],PChar(pWork)+12,iCopyLen);
PChar(pWork) := PChar(pWork)+FNI.dwNextEntryOffset;
until FNI.dwNextEntryOffset = 0;
SetLength(sResult,iCopyLen);
ZeroMemory(@sResult[1],length(sResult));
if WideCharToMultiByte(GetACP,WC_NO_BEST_FIT_CHARS,@FNI.wFilename,iCopyLen,@sResult[1],iCopyLen,nil,nil) <> 0 then begin
end;
end;
end;
finally
FreeMem(pBuf,dwBufLen);
end;
// Destruktor
if (FhDir <> INVALID_HANDLE_VALUE) and (FhDir <> 0) then CloseHandle(FhDir);
if FhComPort <> 0 then CloseHandle(FhComPort);
Ausserdem solltest Du auch einmal prüfen, welche Pfade/Dateien in der Schleife angezeigt werden.
Dass Du auf die Datei nicht zugreifen kannst, wird wohl daran liegen, dass Du sie verschieben willst, sie aber noch von einem anderen Prozess im Zugriff ist (Explorer?)
Ausserdem solltest Du einmal prüfen, ob bei Dir das ReadDirectoryChangesW für jede Veränderung doppelt aufgerufen wird (dazu habe ich hier auch einen Thread offen )
Ich habe mir die asynchrone Lösung erstellt, da ich den Thread ansonsten nicht sauber beenden konnte, wenn ReadDirectoryChangesW auf eine Veränderung gewartet hat.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
|