Code archives/File Utilities/File System Watcher
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This will detect file changes and emit events when they occur. Does not work with Windows 98. | |||||
SuperStrict Import pub.win32 Import brl.eventqueue Import brl.standardio Import brl.threads Import brl.random Private 'Externs Extern "win32" Function GetOverlappedResult:Int(hFile:Int,lpOverlapped:OVERLAPPED,lpNumberOfBytesTransferred:Byte Ptr,bWait:Int) Function ReadDirectoryChangesW(hDirectory:Int,lpBuffer:Byte Ptr,nBufferLength:Int,bWatchSubtree:Int,dwNotifyFilter:Int,lpBytesReturned:Byte Ptr,lpOverlapped:OVERLAPPED,lpCompletionRoutine:Byte Ptr) Function CreateFileA(lpFileName$z,dwDesiredAccess:Int,dwShareMode:Int,lpSecurityAttributes:Byte Ptr,dwCreationDisposition:Int,dwFlagsAndAttributes:Int,hTemplateFile:Int) Function CloseHandle:Int(hObject:Int) Function CreateEventA:Int(lpEventAttributes:Int,bManualReset:Int,bInitialState:Int,lpName$z) 'Function GetLastError:Int() EndExtern 'Constants Const FILE_FLAG_BACKUP_SEMANTICS:Int=$02000000 Const FILE_FLAG_OVERLAPPED:Int=$40000000 Const GENERIC_READ:Int=$80000000 Const FILE_SHARE_READ:Int=$00000001 Const OPEN_EXISTING:Int=3 Const INVALID_HANDLE_VALUE:Int=-1 Const FILE_SHARE_WRITE:Int=$00000002 Const WAIT_FAILED% = $FFFFFFFF Const WAIT_OBJECT_0% = $0 Const WAIT_ABANDONED% = $80 Const WAIT_TIMEOUT% = $102 Const FILE_NOTIFY_CHANGE_FILE_NAME:Int=$00000001 Const FILE_NOTIFY_CHANGE_DIR_NAME:Int=$00000002 Const FILE_NOTIFY_CHANGE_ATTRIBUTES:Int=$00000004 Const FILE_NOTIFY_CHANGE_SIZE:Int=$00000008 Const FILE_NOTIFY_CHANGE_LAST_WRITE:Int=$00000010 Const FILE_NOTIFY_CHANGE_LAST_ACCESS:Int=$00000020 Const FILE_NOTIFY_CHANGE_CREATION:Int=$00000040 Const FILE_NOTIFY_CHANGE_SECURITY:Int=$00000100 'Types Type OVERLAPPED Field Internal:Int Field InternalHigh:Int Field Offset:Int Field OffsetHigh:Int Field hEvent:Int=CreateEventA(0,0,False,Null) Method Delete() If hEvent CloseHandle(hEvent) EndMethod EndType Const FILE_ACTION_ADDED:Int=$00000001 Const FILE_ACTION_REMOVED:Int=$00000002 Const FILE_ACTION_MODIFIED:Int=$00000003 Const FILE_ACTION_RENAMED_OLD_NAME:Int=$00000004 Const FILE_ACTION_RENAMED_NEW_NAME:Int=$00000005 Public 'Event constants Const EVENT_FILECREATED:Int=6870001 Const EVENT_FILEDELETED:Int=6870002 Const EVENT_FILERENAMED:Int=6870003 Const EVENT_FILEMODIFIED:Int=6870004 'FileSystemWatcher type Type TFileSystemWatcher Const flags:Int=FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE Field path:String Field recursive:Int Field buffer:Byte[1024] Field hfile:Int Field overlap:OVERLAPPED=New OVERLAPPED Field mode:Int Field renamedfilepreviousname:String Method Delete() If hfile CloseHandle(hfile) EndMethod Function Create:TFileSystemWatcher(path:String="",recursive:Int=True) Local filesystemwatcher:TFileSystemWatcher filesystemwatcher=New TFileSystemWatcher filesystemwatcher.path=RealPath(path) filesystemwatcher.recursive=recursive filesystemwatcher.hfile=CreateFileA(filesystemwatcher.path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,Null,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,0) If filesystemwatcher.hfile=0 Return Null Return filesystemwatcher EndFunction Method Update() Local bytesreturned:Int Local bytestransferred:Int Local event:TEvent Local bank:TBank Local stream:TStream Local NextEntryOffset:Int Local Action:Int Local FileNameLength:Int Global FileName:String Local pos:Int Local b:Int If mode=0 ReadDirectoryChangesW(Self.hfile,buffer,buffer.length,Self.recursive,Self.flags,Null,Self.overlap,Null) mode=1 EndIf If GetOverlappedResult(Self.hfile,overlap,Varptr bytesreturned,False) mode=0 If bytesreturned bank=CreateStaticBank(buffer,bytesreturned) stream=CreateBankStream(bank) While Not stream.Eof() pos=stream.pos() NextEntryOffset=stream.ReadInt() ' Print "NextEntryOffset: "+NextEntryOffset Action=stream.ReadInt() ' Print "Action: "+action FileNameLength=stream.ReadInt() If FileNameLength=0 Notify "DAMN" ' Print "FileNameLength: "+FileNameLength 'FileName=stream.ReadString(FileNameLength) filename=Self.path+"/" 'Print "STARTING: "+filenamelength For Local n:Int=0 To filenamelength/2-1 b=stream.ReadByte() filename:+Chr(b) stream.ReadByte() 'Print b+", "+Chr(b) Next 'Print "" filename=filename.Replace("\","/") event=New TEvent event.source=filename Select action Case FILE_ACTION_ADDED event.id=EVENT_FILECREATED 'Print Int(Byte Ptr(event.extra)) 'Print "File ~q"+filename+"~q created." Case FILE_ACTION_REMOVED event.id=EVENT_FILEDELETED 'Print "File ~q"+filename+"~q deleted." Case FILE_ACTION_MODIFIED event.id=EVENT_FILEMODIFIED 'Print "File ~q"+filename+"~q modified." Case FILE_ACTION_RENAMED_OLD_NAME renamedfilepreviousname=filename event=Null Case FILE_ACTION_RENAMED_NEW_NAME event.id=EVENT_FILERENAMED event.extra=renamedfilepreviousname 'Print renamedfilepreviousname[1] 'Print renamedfilepreviousname renamedfilepreviousname="" 'Print "File renamed from ~q"+String(event.extra)+"~q to ~q"+String(event.source)+"~q." EndSelect If event EmitEvent(event) If NextEntryOffset stream.seek(pos+NextEntryOffset) Else Exit Wend 'Print "DONE" EndIf EndIf EndMethod EndType Function CreateFileSystemWatcher:TFileSystemWatcher(path:String,recursive:Int=True) Return TFileSystemWatcher.Create(path,recursive) EndFunction |
Comments
None.
Code Archives Forum