New Lexer:
;Function WatchDirectory()
;
;Parameters
; WatchFolder - Specify a valid path to watch for changes in.
; - can be directory or drive (e.g. c:\ or c:\Temp)
; - can be network path e.g. \\192.168.2.101\Shared)
; - can include last backslash. e.g. C:\Temp\ (will be reported same form)
;
; WatchSubDirs - Specify whether to search in subfolders
;
;StopWatching - THIS SHOULD BE DONE BEFORE EXITING SCRIPT AT LEAST (OnExit)
; Call WatchDirectory() without parameters to stop watching all directories
;
;ReportChanges
; Call WatchDirectory("ReportingFunctionName") to process registered changes.
; Syntax of ReportingFunctionName(Action,Folder,File)
;
; Example
/*
#Persistent
OnExit,Exit
WatchDirectory("C:\Windows",1)
SetTimer,WatchFolder,100
Return
WatchFolder:
WatchDirectory("RegisterChanges")
Return
RegisterChanges(action,folder,file){
static
#1:="New File", #2:="Deleted", #3:="Modified", #4:="Renamed From", #5:="Renamed To"
ToolTip % #%Action% "`n" folder . (SubStr(folder,0)="\" ? "" : "\") . file
}
Exit:
WatchDirectory()
ExitApp
*/
WatchDirectory(WatchFolder="", WatchSubDirs=true)
{
static
local hDir, hEvent, r, Action, FileNameLen, pFileName, Restart, CurrentFolder, PointerFNI, _SizeOf_FNI_=65536
nReadLen := 0
If !(WatchFolder){
Gosub, StopWatchingDirectories
} else if IsFunc(WatchFolder) {
r := DllCall("MsgWaitForMultipleObjectsEx", UInt, DirIdx, UInt, &DirEvents, UInt, -1, UInt, 0x4FF, UInt, 0x6) ;Timeout=-1
if !(r >= 0 && r < DirIdx)
Return
r += 1
CurrentFolder := Dir%r%Path
PointerFNI := &Dir%r%FNI
DllCall( "GetOverlappedResult", UInt, hDir, UInt, &Dir%r%Overlapped, UIntP, nReadLen, Int, true )
Loop {
pNext := NumGet( PointerFNI + 0 )
Action := NumGet( PointerFNI + 4 )
FileNameLen := NumGet( PointerFNI + 8 )
pFileName := ( PointerFNI + 12 )
If (Action < 0x6){
VarSetCapacity( FileNameANSI, FileNameLen )
DllCall( "WideCharToMultiByte",UInt,0,UInt,0,UInt,pFileName,UInt,FileNameLen,Str,FileNameANSI,UInt,FileNameLen,UInt,0,UInt,0)
%WatchFolder%(Action,CurrentFolder,SubStr( FileNameANSI, 1, FileNameLen/2 ))
}
If (!pNext or pNext = 4129024)
Break
Else
PointerFNI := (PointerFNI + pNext)
}
DllCall( "ResetEvent", UInt,NumGet( Dir%r%Overlapped, 16 ) )
Gosub, ReadDirectoryChanges
return r
} else {
Loop % (DirIdx) {
If InStr(WatchFolder, Dir%A_Index%Path){
If (Dir%A_Index%Subdirs)
Return
} else if InStr(Dir%A_Index%Path, WatchFolder) {
If (WatchSubDirs){
DllCall( "CloseHandle", UInt,Dir%A_Index% )
DllCall( "CloseHandle", UInt,NumGet(Dir%A_Index%Overlapped, 16) )
Restart := DirIdx, DirIdx := A_Index
}
}
}
If !Restart
DirIdx += 1
r:=DirIdx
hDir := DllCall( "CreateFile"
, Str , WatchFolder
, UInt , ( FILE_LIST_DIRECTORY := 0x1 )
, UInt , ( FILE_SHARE_READ := 0x1 )
| ( FILE_SHARE_WRITE := 0x2 )
| ( FILE_SHARE_DELETE := 0x4 )
, UInt , 0
, UInt , ( OPEN_EXISTING := 0x3 )
, UInt , ( FILE_FLAG_BACKUP_SEMANTICS := 0x2000000 )
| ( FILE_FLAG_OVERLAPPED := 0x40000000 )
, UInt , 0 )
Dir%r% := hDir
Dir%r%Path := WatchFolder
Dir%r%Subdirs := WatchSubDirs
VarSetCapacity( Dir%r%FNI, _SizeOf_FNI_ )
VarSetCapacity( Dir%r%Overlapped, 20, 0 )
DllCall( "CloseHandle", UInt,hEvent )
hEvent := DllCall( "CreateEvent", UInt,0, Int,true, Int,false, UInt,0 )
NumPut( hEvent, Dir%r%Overlapped, 16 )
if ( VarSetCapacity(DirEvents) < DirIdx*4 and VarSetCapacity(DirEvents, DirIdx*4 + 60))
Loop %DirIdx%
{
If (SubStr(Dir%A_Index%Path,1,1)!="-"){
action++
NumPut( NumGet( Dir%action%Overlapped, 16 ), DirEvents, action*4-4 )
}
}
NumPut( hEvent, DirEvents, DirIdx*4-4)
Gosub, ReadDirectoryChanges
If Restart
DirIdx = %Restart%
}
Return
StopWatchingDirectories:
Loop % (DirIdx) {
DllCall( "CloseHandle", UInt,Dir%A_Index% )
DllCall( "CloseHandle", UInt,NumGet(Dir%A_Index%Overlapped, 16) )
Dir%A_Index%=
Dir%A_Index%Path=
Dir%A_Index%Subdirs=
Dir%A_Index%FNI=
DllCall( "CloseHandle", UInt, NumGet(Dir%A_Index%Overlapped,16) )
VarSetCapacity(Dir%A_Index%Overlapped,0)
}
DirIdx=
VarSetCapacity(DirEvents,0)
Return
ReadDirectoryChanges:
DllCall( "ReadDirectoryChangesW"
, UInt , Dir%r%
, UInt , &Dir%r%FNI
, UInt , _SizeOf_FNI_
, UInt , Dir%r%SubDirs
, UInt , ( FILE_NOTIFY_CHANGE_FILE_NAME := 0x1 )
| ( FILE_NOTIFY_CHANGE_DIR_NAME := 0x2 )
| ( FILE_NOTIFY_CHANGE_ATTRIBUTES := 0x4 )
| ( FILE_NOTIFY_CHANGE_SIZE := 0x8 )
| ( FILE_NOTIFY_CHANGE_LAST_WRITE := 0x10 )
| ( FILE_NOTIFY_CHANGE_CREATION := 0x40 )
| ( FILE_NOTIFY_CHANGE_SECURITY := 0x100 )
, UInt , 0
, UInt , &Dir%r%Overlapped
, UInt , 0 )
Return
}