Thema: Delphi Festplattenzugriffe

Einzelnen Beitrag anzeigen

Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.117 Beiträge
 
Delphi 11 Alexandria
 
#19

Re: Festplattenzugriffe

  Alt 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
  Mit Zitat antworten Zitat