program DirMonDOS; {$mode objfpc}{$H+} uses {$IFDEF UNIX} {$IFDEF UseCThreads} cthreads, {$ENDIF} {$ENDIF} Classes, crt, JwaWindows, SysUtils; var FPathName: string; FDirHandle: THandle; FBuffer: array[0..9999] of byte; FBytesReturned: dword; FOverLapped: TOverlapped; FOverResult: boolean; FFileNotifyInformation: PFileNotifyInformation; FOffset: dword; FAction: dword; FActionStr: string; FFilename: string; FLen: dword; FTerminate: boolean; FLastError: dword; FNotifyFilter: DWord; FLooping: boolean; begin { Répertoire à surveiller } FPathName := 'J:\'; { Initialisation des variables } FTerminate := False; FLooping := False; ZeroMemory(@FBuffer, sizeof(FBuffer)); FNotifyFilter := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_LAST_WRITE; { FILE_NOTIFY_CHANGE_FILE_NAME = 1; FILE_NOTIFY_CHANGE_DIR_NAME = 2; FILE_NOTIFY_CHANGE_ATTRIBUTES = 4; FILE_NOTIFY_CHANGE_SIZE = 8; FILE_NOTIFY_CHANGE_LAST_WRITE = 16; FILE_NOTIFY_CHANGE_LAST_ACCESS = 32; FILE_NOTIFY_CHANGE_CREATION = 64; FILE_NOTIFY_CHANGE_SECURITY = 256; } writeln('Press [s] to exit'); WriteLn('Surveillance du dossier [', FPathName, ']'); { Récuperation du Handle du Répertoire a surveiller } FDirHandle := CreateFile(PChar(FPathName), 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); WriteLn('Handle du dossier [', FDirHandle, ']'); if FDirHandle <> INVALID_HANDLE_VALUE then begin try { Bouclage jusqu'a ce que Terminate=True } repeat { Mise en place de la surveillance } if ReadDirectoryChangesW(FDirHandle, @FBuffer, sizeOf(FBuffer), True, FNotifyFilter, @FBytesReturned, @FOverLapped, nil) then begin { Bouclage jusqu'a ce que FOverResult=True } repeat { Si FOverResult = True, cela signifie qu'il y a eu des modifications } FOverResult := GetOverlappedResult(FDirHandle, FOverLapped, FBytesReturned, False); { Je capture GetLastError ci-dessous, car il peut etre modifié par d'autres instructions, comme un WriteLn par exemple } FLastError := GetLastError; { Affichage des informations pour faire beau } if not FOverResult and not FLooping then begin Writeln('Looping...'); FLooping := True; end; sleep(100); { Verification si on a pressé la touche [S] pour arreter le processus } if KeyPressed and (ReadKey = 's') then FTerminate := True; until FOverResult or (FLastError <> ERROR_IO_INCOMPLETE) or FTerminate; FLooping := False; if FOverResult then begin Writeln('--- begin modification ---'); { Positionnement sur le debut du Buffer } pointer(FFileNotifyInformation) := @FBuffer[0]; repeat FOffset := FFileNotifyInformation^.NextEntryOffset; FAction := FFileNotifyInformation^.Action; { FLen = FileNameLength/2 car FileName est codé en WideString et WideString est 2x plus long que AnsiString ->https://wiki.freepascal.org/Character_and_string_types/fr } FLen := FFileNotifyInformation^.FileNameLength div 2; WideCharLenToStrVar(@(FFileNotifyInformation^.FileName), FLen, FFilename); case FAction of FILE_ACTION_ADDED: FActionStr := 'Created'; FILE_ACTION_REMOVED: FActionStr := 'Deleted'; FILE_ACTION_MODIFIED: FActionStr := 'Modified'; FILE_ACTION_RENAMED_OLD_NAME: FActionStr := 'RenamedFrom'; FILE_ACTION_RENAMED_NEW_NAME: FActionStr := 'RenamedTo'; else FActionStr := '???'; end; { Affichage du résultat } WriteLn('Action [', FAction, '|', FActionStr, '] len[', FLen, '] sur fichier [', FFilename, ']'); { Positionnement sur le prochain FFileNotifyInformation } pointer(FFileNotifyInformation) := pointer(FFileNotifyInformation) + FOffset; until FOffset = 0; { Nettoyage du Buffer pour eviter d'accumuler des parasites surtout dans Filename } ZeroMemory(@FBuffer, sizeof(FBuffer)); Writeln('--- end modification ---'); end; end; until FTerminate; finally CloseHandle(FDirHandle); end; end else Writeln('Dir Handle invalid'); Writeln('Press to exit'); Readln; end.