Joined: June 18th, 2008, 8:36 am Posts: 4923 Location: AHK Forum
|
This functionality already exist in Crazy Scripting : FolderSpy v0.96 [ Synchronous ] and WatchDirectory()Again many thanks to SKAN and Lexikos  Note  You will need latest AutoHotkey_L or AutoHotkey_H to use these functions. Also latest _Struct() class is required.
It's now better, faster, more accurate and has got great filtering options. Enjoy 
How To Use wrote: [b]All you need is a function in your script that accepts 2 parameters
- When a file is changed, both parameters will contain same filename/path - When a file is deleted, it is passed in first parameter and second parameter will be empty - When a new file is created, first parameter is empty and second contains filename/path - When a file is renamed, first parameter contains old filename/path and second new filename/path
WatchDirectory(dir[\*|...],func,watchfor) accepts up to 3 parameters - dir, can be a folder/directory (last backslash is optional) - - include * in the end of your directory to watch in sub folders - - after that you can include file name filters separated by pipe '|', here you have following options: - - - use * and ? wildcard - - - include Back Slash in front = match beginning of filename - - - include Back Slash at the end = match end of filename - - - include Back Slash anywhere in the middle to search in complete file path - - - E.g. following will search for files that start with a and end with .txt or .iniCode: WatchDirectory("C:\temp\*|.txt\|.ini\|\a","ReportChanges") - func, a function to be launched when changes in corresponding folder occur - - when you omit func, last used function will be used - Your function must accept 2 parameters - - When new file is created: - - - first parameter will be empty - - - second parameter will contain the filepath - - When file is deleted - - - second parameter will be empty - - - first parameter will contain the filepath - - When file is modified both parameters contain same filepath - - When file is renamed - - - first parameter will contain old filename - - - second parameter will contain new filename - watchfor can be used to report only specific changes - - therefore include one or several of following values i - - 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 - - these values must be separated by |, by default all changes are reported.Code: WatchDirectory("C:\Temp","ReportFunction",0x1|0x2|0x8|0x40) To stop watching Directory, at least when script exits WatchDirectory needs to be called with empty parameterCode: WatchDirectory("") To stop watching a specific Directory, include "" for second parameter. E.g. Code: WatchDirectory("C:\Temp","")
Example and WatchDirectory() FunctionCode: #Persistent SetBatchLines,-1 SetWinDelay,-1 OnExit, GuiClose
WatchFolders=C:\Temp*|%A_Temp%*|%A_Desktop%|%A_DesktopCommon%|%A_MyDocuments%*|%A_ScriptDir%|%A_WinDir%* Gui,+Resize Gui,Add,ListView,r10 w800 vWatchingDirectoriesList HWNDhList1 gShow,WatchingDirectories|WatchingSubdirs Loop,Parse,WatchFolders,| WatchDirectory(A_LoopField,"ReportChanges") ,LV_Add("",SubStr(A_LoopField,0)="*" ? (SubStr(A_LoopField,1,StrLen(A_LoopField)-1)) : A_LoopField ,SubStr(A_LoopField,0)="*" ? 1 : 0) LV_ModifyCol(1,"AutoHdr") Gui,Add,ListView,r30 w800 vChangesList HWNDhList2 gShow,Time|FileChangedFrom - Double click to show in Explorer|FileChangedTo - Double click to show in Explorer Gui,Add,Button,gAdd Default,Watch new directory Gui,Add,Button,gDelete x+1,Stop watching all directories Gui,Add,Button,gClear x+1,Clear List Gui,Add,StatusBar,,Changes Registered Gui, Show
Return
Clear: Gui,ListView, ChangesList LV_Delete() Return
Delete: WatchDirectory("") Gui,ListView, WatchingDirectoriesList LV_Delete() Gui,ListView, ChangesList TotalChanges:=0 SB_SetText("Changes Registered") Return
Show: If A_GuiEvent!=DoubleClick Return Gui,ListView,%A_GuiControl% LV_GetText(file,A_EventInfo,2) If file= LV_GetText(file,A_EventInfo,3) Run,% "explorer.exe /e`, /n`, /select`," . file Return
Add: Gui,+OwnDialogs dir= FileSelectFolder,dir,,3,Select directory to watch for If !dir Return SetTimer,SetMsgBoxButtons,-10 MsgBox, 262146,Add directory,Would you like to watch for changes in:`n%dir%
if SubStr(dir,0)!="\" dir.="\"
Gui,ListView, WatchingDirectoriesList IfMsgBox Retry WatchDirectory(dir "*"),LV_Add("",dir,1) IfMsgBox Ignore WatchDirectory(dir),LV_Add("",dir,0) LV_ModifyCol(1,"AutoHdr") Gui,ListView, ChangesList Return
SetMsgBoxButtons: WinWait, ahk_class #32770 WinActivate WinWaitActive ControlSetText,Button2,&Incl. subdirs, ahk_class #32770 ControlSetText,Button3,&Excl. subdirs, ahk_class #32770 Return
ReportChanges(from,to){ global TotalChanges Gui,ListView, ChangesList LV_Insert(1,"",A_Hour ":" A_Min ":" A_Sec ":" A_MSec,from,to) LV_ModifyCol() LV_ModifyCol(1,"AutoHdr"),LV_ModifyCol(2,"AutoHdr") TotalChanges++ SB_SetText("Changes Registered " . TotalChanges) }
GuiClose: WatchDirectory("") ;Stop Watching Directory = delete all directories ExitApp
#include <_Struct> WatchDirectory(p*){ global _Struct ;Structures static FILE_NOTIFY_INFORMATION:="DWORD NextEntryOffset,DWORD Action,DWORD FileNameLength,WCHAR FileName[1]" static OVERLAPPED:="ULONG_PTR Internal,ULONG_PTR InternalHigh,{struct{DWORD offset,DWORD offsetHigh},PVOID Pointer},HANDLE hEvent" ;Variables static running,sizeof_FNI=65536,temp1:=VarSetCapacity(nReadLen,8),WatchDirectory:=RegisterCallback("WatchDirectory","F",0,0) static timer,ReportToFunction,LP,temp2:=VarSetCapacity(LP,(260)*(A_PtrSize/2),0) static @:=Object(),reconnect:=Object(),#:=Object(),DirEvents,StringToRegEx="\\\|.\.|+\+|[\[|{\{|(\(|)\)|^\^|$\$|?\.?|*.*" ;ReadDirectoryChanges related static 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 static FILE_ACTION_ADDED=1,FILE_ACTION_REMOVED=2,FILE_ACTION_MODIFIED=3 ,FILE_ACTION_RENAMED_OLD_NAME=4,FILE_ACTION_RENAMED_NEW_NAME=5 static OPEN_EXISTING=3,FILE_FLAG_BACKUP_SEMANTICS=0x2000000,FILE_FLAG_OVERLAPPED=0x40000000 ,FILE_SHARE_DELETE=4,FILE_SHARE_WRITE=2,FILE_SHARE_READ=1,FILE_LIST_DIRECTORY=1 If p.MaxIndex(){ If (p.MaxIndex()=1 && p.1=""){ for i,folder in # DllCall("CloseHandle","Uint",@[folder].hD),DllCall("CloseHandle","Uint",@[folder].O.hEvent) ,@.Remove(folder) #:=Object() DirEvents:=new _Struct("HANDLE[1000]") DllCall("KillTimer","Uint",0,"Uint",timer) timer= Return 0 } else { if p.2 ReportToFunction:=p.2 If !IsFunc(ReportToFunction) Return -1 ;DllCall("MessageBox","Uint",0,"Str","Function " ReportToFunction " does not exist","Str","Error Missing Function","UInt",0) RegExMatch(p.1,"^([^/\*\?<>\|""]+)(\*)?(\|.+)?$",dir) if (SubStr(dir1,0)="") StringTrimRight,dir1,dir1,1 StringTrimLeft,dir3,dir3,1 If (p.MaxIndex()=2 && p.2=""){ for i,folder in # If (dir1=SubStr(folder,1,StrLen(folder)-1)) Return 0 ,DirEvents[i]:=DirEvents[#.MaxIndex()],DirEvents[#.MaxIndex()]:=0 @.Remove(folder),#[i]:=#[#.MaxIndex()],#.Remove(i) Return 0 } } if !InStr(FileExist(dir1),"D") Return -1 ;DllCall("MessageBox","Uint",0,"Str","Folder " dir1 " does not exist","Str","Error Missing File","UInt",0) for i,folder in # { If (dir1=SubStr(folder,1,StrLen(folder)-1) || (InStr(dir1,folder) && @[folder].sD)) Return 0 else if (InStr(SubStr(folder,1,StrLen(folder)-1),dir1 "") && dir2){ ;replace watch DllCall("CloseHandle","Uint",@[folder].hD),DllCall("CloseHandle","Uint",@[folder].O.hEvent),reset:=i } } LP:=SubStr(LP,1,DllCall("GetLongPathName","Str",dir1,"Uint",&LP,"Uint",VarSetCapacity(LP))) "" If !(reset && @[reset]:=LP) #.Insert(LP) @[LP,"dir"]:=LP @[LP].hD:=DllCall("CreateFile","Str",StrLen(LP)=3?SubStr(LP,1,2):LP,"UInt",0x1,"UInt",0x1|0x2|0x4 ,"UInt",0,"UInt",0x3,"UInt",0x2000000|0x40000000,"UInt",0) @[LP].sD:=(dir2=""?0:1)
Loop,Parse,StringToRegEx,| StringReplace,dir3,dir3,% SubStr(A_LoopField,1,1),% SubStr(A_LoopField,2),A StringReplace,dir3,dir3,%A_Space%,\s,A Loop,Parse,dir3,| { If A_Index=1 dir3= pre:=(SubStr(A_LoopField,1,2)="\"?2:0) succ:=(SubStr(A_LoopField,-1)="\"?2:0) dir3.=(dir3?"|":"") (pre?"\\\K":"") . SubStr(A_LoopField,1+pre,StrLen(A_LoopField)-pre-succ) . ((!succ && !InStr(SubStr(A_LoopField,1+pre,StrLen(A_LoopField)-pre-succ),""))?"[^\\]*$":"") (succ?"$":"") } @[LP].FLT:="i)" dir3 @[LP].FUNC:=ReportToFunction @[LP].CNG:=(p.3?p.3:(0x1|0x2|0x4|0x8|0x10|0x40|0x100)) If !reset { @[LP].SetCapacity("pFNI",sizeof_FNI) @[LP].FNI:=new _Struct(FILE_NOTIFY_INFORMATION,@[LP].GetAddress("pFNI")) @[LP].O:=new _Struct(OVERLAPPED) } @[LP].O.hEvent:=DllCall("CreateEvent","Uint",0,"Int",1,"Int",0,"UInt",0) If (!DirEvents) DirEvents:=new _Struct("HANDLE[1000]") DirEvents[reset?reset:#.MaxIndex()]:=@[LP].O.hEvent DllCall("ReadDirectoryChangesW","UInt",@[LP].hD,"UInt",@[LP].FNI[],"UInt",sizeof_FNI ,"Int",@[LP].sD,"UInt",@[LP].CNG,"UInt",0,"UInt",@[LP].O[],"UInt",0) Return timer:=DllCall("SetTimer","Uint",0,"UInt",timer,"Uint",50,"UInt",WatchDirectory) } else { Sleep, 0 for LP in reconnect { If (FileExist(@[LP].dir) && reconnect.Remove(LP)){ DllCall("CloseHandle","Uint",@[LP].hD) @[LP].hD:=DllCall("CreateFile","Str",StrLen(@[LP].dir)=3?SubStr(@[LP].dir,1,2):@[LP].dir,"UInt",0x1,"UInt",0x1|0x2|0x4 ,"UInt",0,"UInt",0x3,"UInt",0x2000000|0x40000000,"UInt",0) DllCall("ResetEvent","UInt",@[LP].O.hEvent) DllCall("ReadDirectoryChangesW","UInt",@[LP].hD,"UInt",@[LP].FNI[],"UInt",sizeof_FNI ,"Int",@[LP].sD,"UInt",@[LP].CNG,"UInt",0,"UInt",@[LP].O[],"UInt",0) } } if !( (r:=DllCall("MsgWaitForMultipleObjectsEx","UInt",#.MaxIndex() ,"UInt",DirEvents[],"UInt",0,"UInt",0x4FF,"UInt",6))>=0 && r<#.MaxIndex() ){ return } DllCall("KillTimer", UInt,0, UInt,timer) LP:=#[r+1],DllCall("GetOverlappedResult","UInt",@[LP].hD,"UInt",@[LP].O[],"UIntP",nReadLen,"Int",1) If (A_LastError=64){ ; ERROR_NETNAME_DELETED - The specified network name is no longer available. If !FileExist(@[LP].dir) ; If folder does not exist add to reconnect routine reconnect.Insert(LP,LP) } else Loop { FNI:=A_Index>1?(new _Struct(FILE_NOTIFY_INFORMATION,FNI[]+FNI.NextEntryOffset)):(new _Struct(FILE_NOTIFY_INFORMATION,@[LP].FNI[])) If (FNI.Action < 0x6){ FileName:=@[LP].dir . StrGet(FNI.FileName[""],FNI.FileNameLength/2,"UTF-16") If (FNI.Action=FILE_ACTION_RENAMED_OLD_NAME) FileFromOptional:=FileName If (@[LP].FLT="" || RegExMatch(FileName,@[LP].FLT) || FileFrom) If (FNI.Action=FILE_ACTION_ADDED){ FileTo:=FileName } else If (FNI.Action=FILE_ACTION_REMOVED){ FileFrom:=FileName } else If (FNI.Action=FILE_ACTION_MODIFIED){ FileFrom:=FileTo:=FileName } else If (FNI.Action=FILE_ACTION_RENAMED_OLD_NAME){ FileFrom:=FileName } else If (FNI.Action=FILE_ACTION_RENAMED_NEW_NAME){ FileTo:=FileName } If (FNI.Action != 4 && (FileTo . FileFrom) !="") @[LP].Func(FileFrom=""?FileFromOptional:FileFrom,FileTo) } } Until (!FNI.NextEntryOffset || ((FNI[]+FNI.NextEntryOffset) > (@[LP].FNI[]+sizeof_FNI-12))) DllCall("ResetEvent","UInt",@[LP].O.hEvent) DllCall("ReadDirectoryChangesW","UInt",@[LP].hD,"UInt",@[LP].FNI[],"UInt",sizeof_FNI ,"Int",@[LP].sD,"UInt",@[LP].CNG,"UInt",0,"UInt",@[LP].O[],"UInt",0) timer:=DllCall("SetTimer","Uint",0,"UInt",timer,"Uint",50,"UInt",WatchDirectory) Return } Return } AutoHotkey V2 version:Code: SetWinDelay,-1 OnExit, GuiClose
WatchFolders:="C:\Temp*|%A_Temp%*|%A_Desktop%|%A_DesktopCommon%|%A_MyDocuments%*|%A_ScriptDir%|%A_WinDir%*" Gui,+Resize Gui,Add,ListView,r10 w800 vWatchingDirectoriesList HWNDhList1 gShow,WatchingDirectories|WatchingSubdirs LoopParse,%WatchFolders%,| WatchDirectory(A_LoopField,"ReportChanges") ,LV_Add("",SubStr(A_LoopField,0)="*" ? (SubStr(A_LoopField,1,StrLen(A_LoopField)-1)) : A_LoopField ,SubStr(A_LoopField,0)="*" ? 1 : 0) LV_ModifyCol(1,"AutoHdr") Gui,Add,ListView,r30 w800 vChangesList HWNDhList2 gShow,Time|FileChangedFrom - Double click to show in Explorer|FileChangedTo - Double click to show in Explorer Gui,Add,Button,gAdd Default,Watch new directory Gui,Add,Button,gDelete x+1,Stop watching all directories Gui,Add,Button,gClear x+1,Clear List Gui,Add,StatusBar,,Changes Registered Gui, Show
Return
Clear: Gui,ListView, ChangesList LV_Delete() Return
Delete: WatchDirectory("") Gui,ListView, WatchingDirectoriesList LV_Delete() Gui,ListView, ChangesList TotalChanges:=0 SB_SetText("Changes Registered") Return
Show: If A_GuiEvent!=DoubleClick Return Gui,ListView,%A_GuiControl% LV_GetText(file,A_EventInfo,2) If file= LV_GetText(file,A_EventInfo,3) Run,% "explorer.exe /e`, /n`, /select`," . file Return
Add: Gui,+OwnDialogs dir:="" FileSelectFolder,dir,,3,Select directory to watch for If !dir Return SetTimer,SetMsgBoxButtons,-10 MsgBox, 262146,Add directory,Would you like to watch for changes in:`n%dir%
Gui,ListView, WatchingDirectoriesList If (A_MsgBoxResult="Retry") WatchDirectory(dir "*"),LV_Add("",dir,1) If (A_MsgBoxResult="Ignore") WatchDirectory(dir),LV_Add("",dir,0) LV_ModifyCol(1,"AutoHdr") Gui,ListView, ChangesList Return
SetMsgBoxButtons: WinWait, ahk_class #32770 WinActivate WinWaitActive ControlSetText,Button2,&Incl. subdirs, ahk_class #32770 ControlSetText,Button3,&Excl. subdirs, ahk_class #32770 Return
ReportChanges(from,to){ global TotalChanges Gui,ListView, ChangesList LV_Insert(1,"",A_Hour ":" A_Min ":" A_Sec ":" A_MSec,from,to) LV_ModifyCol() LV_ModifyCol(1,"AutoHdr"),LV_ModifyCol(2,"AutoHdr") TotalChanges++ SB_SetText("Changes Registered " . TotalChanges) }
GuiClose: WatchDirectory("") ;Stop Watching Directory = delete all directories ExitApp
#include <_Struct> WatchDirectory(p*){ global _Struct ;Structures static FILE_NOTIFY_INFORMATION:="DWORD NextEntryOffset,DWORD Action,DWORD FileNameLength,WCHAR FileName[1]" static OVERLAPPED:="ULONG_PTR Internal,ULONG_PTR InternalHigh,{struct{DWORD offset,DWORD offsetHigh},PVOID Pointer},HANDLE hEvent" ;Variables static running,sizeof_FNI:=65536,temp1:=VarSetCapacity(nReadLen,8),WatchDirectory:=RegisterCallback("WatchDirectory","F",0,0) static timer,ReportToFunction,LP,temp2:=VarSetCapacity(LP,(260)*(A_PtrSize/2),0) static __:=Object(),reconnect:=Object(),_:=Object(),DirEvents,StringToRegEx:="\\\|.\.|+\+|[\[|{\{|(\(|)\)|^\^|$\$|?\.?|*.*" ;ReadDirectoryChanges related static 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 static FILE_ACTION_ADDED:=1,FILE_ACTION_REMOVED:=2,FILE_ACTION_MODIFIED:=3 ,FILE_ACTION_RENAMED_OLD_NAME:=4,FILE_ACTION_RENAMED_NEW_NAME:=5 static OPEN_EXISTING:=3,FILE_FLAG_BACKUP_SEMANTICS:=0x2000000,FILE_FLAG_OVERLAPPED:=0x40000000 ,FILE_SHARE_DELETE:=4,FILE_SHARE_WRITE:=2,FILE_SHARE_READ:=1,FILE_LIST_DIRECTORY:=1 If p.MaxIndex(){ If (p.MaxIndex()=1 && p.1=""){ for i,folder in _ DllCall("CloseHandle","Uint",__[folder].hD),DllCall("CloseHandle","Uint",__[folder].O.hEvent) ,__.Remove(folder) _:=Object() DirEvents:=new _Struct("HANDLE[1000]") DllCall("KillTimer","Uint",0,"Uint",timer) timer:="" Return 0 } else { if p.2 ReportToFunction:=p.2 If !IsFunc(ReportToFunction) Return -1 ;DllCall("MessageBox","Uint",0,"Str","Function " ReportToFunction " does not exist","Str","Error Missing Function","UInt",0) RegExMatch(p.1,"^([^/\*\?<>\|""]+)(\*)?(\|.+)?$",dir) loop % dir.count() dir%A_Index%:=dir[A_Index] if (SubStr(dir1,-1)="") dir1:=SubStr(dir1,1,-1) dir3:=SubStr(dir3,2) If (p.MaxIndex()=2 && p.2=""){ for i,folder in _ If (dir1=SubStr(folder,1,-1)) Return 0 ,DirEvents[i]:=DirEvents[_.MaxIndex()],DirEvents[_.MaxIndex()]:=0 __.Remove(folder),_[i]:=_[_.MaxIndex()],_.Remove(i) Return 0 } } if !InStr(FileExist(dir1),"D") Return -1 ;DllCall("MessageBox","Uint",0,"Str","Folder " dir1 " does not exist","Str","Error Missing File","UInt",0) for i,folder in _ { If (dir1=SubStr(folder,1,-1) || (InStr(dir1,folder) && __[folder].sD)) Return 0 else if (InStr(SubStr(folder,1,-1),dir1 "") && dir2){ ;replace watch DllCall("CloseHandle","PTR",__[folder].hD),DllCall("CloseHandle","PTR",__[folder].O.hEvent),reset:=i } } LP:=SubStr(LP,1,DllCall("GetLongPathName","Str",dir1,"STR",LP,"Uint",VarSetCapacity(LP))) "" If !(reset && __[reset]:=LP) _.Insert(LP) __[LP,"dir"]:=LP __[LP].hD:=DllCall("CreateFile","Str",StrLen(LP)=3?SubStr(LP,1,2):LP,"UInt",0x1,"UInt",0x1|0x2|0x4 ,"PTR",0,"UInt",0x3,"UInt",0x2000000|0x40000000,"PTR",0) __[LP].sD:=(dir2=""?0:1)
LoopParse,%StringToRegEx%,| StrReplace,dir3,%dir3%,% SubStr(A_LoopField,1,1),% SubStr(A_LoopField,2) StrReplace,dir3,%dir3%,%A_Space%,\s LoopParse,%dir3%,| { If A_Index=1 dir3:="" pre:=(SubStr(A_LoopField,1,2)="\"?2:0) succ:=(SubStr(A_LoopField,-2)="\"?2:0) dir3.=(dir3?"|":"") (pre?"\\\K":"") . SubStr(A_LoopField,1+pre,StrLen(A_LoopField)-pre-succ) . ((!succ && !InStr(SubStr(A_LoopField,1+pre,StrLen(A_LoopField)-pre-succ),""))?"[^\\]*$":"") (succ?"$":"") } __[LP].FLT:="i)" dir3 __[LP].FUNC:=ReportToFunction __[LP].CNG:=(p.3?p.3:(0x1|0x2|0x4|0x8|0x10|0x40|0x100)) If !reset { __[LP].SetCapacity("pFNI",sizeof_FNI) __[LP].FNI:=new _Struct(FILE_NOTIFY_INFORMATION,__[LP].GetAddress("pFNI")) __[LP].O:=new _Struct(OVERLAPPED) } __[LP].O.hEvent:=DllCall("CreateEvent","Uint",0,"Int",1,"Int",0,"UInt",0) If (!DirEvents) DirEvents:=new _Struct("HANDLE[1000]") DirEvents[reset?reset:_.MaxIndex()]:=__[LP].O.hEvent DllCall("ReadDirectoryChangesW","UInt",__[LP].hD,"UInt",__[LP].FNI[""],"UInt",sizeof_FNI ,"Int",__[LP].sD,"UInt",__[LP].CNG,"UInt",0,"UInt",__[LP].O[""],"UInt",0) Return timer:=DllCall("SetTimer","Uint",0,"UInt",timer,"Uint",50,"UInt",WatchDirectory) } else { Sleep, 0 for LP in reconnect { If (FileExist(__[LP].dir) && reconnect.Remove(LP)){ DllCall("CloseHandle","Uint",__[LP].hD) __[LP].hD:=DllCall("CreateFile","Str",StrLen(__[LP].dir)=3?SubStr(__[LP].dir,1,2):__[LP].dir,"UInt",0x1,"UInt",0x1|0x2|0x4 ,"UInt",0,"UInt",0x3,"UInt",0x2000000|0x40000000,"UInt",0) DllCall("ResetEvent","UInt",__[LP].O.hEvent) DllCall("ReadDirectoryChangesW","UInt",__[LP].hD,"UInt",__[LP].FNI[""],"UInt",sizeof_FNI ,"Int",__[LP].sD,"UInt",__[LP].CNG,"UInt",0,"UInt",__[LP].O[""],"UInt",0) } } if !( (r:=DllCall("MsgWaitForMultipleObjectsEx","UInt",_.MaxIndex() ,"UInt",DirEvents[""],"UInt",0,"UInt",0x4FF,"UInt",6))>=0 && r<_.MaxIndex() ){ return } DllCall("KillTimer", UInt,0, UInt,timer) LP:=_[r+1],DllCall("GetOverlappedResult","UInt",__[LP].hD,"UInt",__[LP].O[""],"UIntP",nReadLen,"Int",1) If (A_LastError=64){ ; ERROR_NETNAME_DELETED - The specified network name is no longer available. If !FileExist(__[LP].dir) ; If folder does not exist add to reconnect routine reconnect.Insert(LP,LP) } else Loop { FNI:=A_Index>1?(new _Struct(FILE_NOTIFY_INFORMATION,FNI[""]+FNI.NextEntryOffset)):(new _Struct(FILE_NOTIFY_INFORMATION,__[LP].FNI[""])) If (FNI.Action < 0x6){ FileName:=__[LP].dir . StrGet(FNI.FileName[""],FNI.FileNameLength/2,"UTF-16") If (FNI.Action=FILE_ACTION_RENAMED_OLD_NAME) FileFromOptional:=FileName If (__[LP].FLT="" || RegExMatch(FileName,__[LP].FLT) || FileFrom) If (FNI.Action=FILE_ACTION_ADDED){ FileTo:=FileName } else If (FNI.Action=FILE_ACTION_REMOVED){ FileFrom:=FileName } else If (FNI.Action=FILE_ACTION_MODIFIED){ FileFrom:=FileTo:=FileName } else If (FNI.Action=FILE_ACTION_RENAMED_OLD_NAME){ FileFrom:=FileName } else If (FNI.Action=FILE_ACTION_RENAMED_NEW_NAME){ FileTo:=FileName } If (FNI.Action != 4 && (FileTo . FileFrom) !="") __[LP].Func(FileFrom=""?FileFromOptional:FileFrom,FileTo) } } Until (!FNI.NextEntryOffset || ((FNI[""]+FNI.NextEntryOffset) > (__[LP].FNI[""]+sizeof_FNI-12))) DllCall("ResetEvent","UInt",__[LP].O.hEvent) DllCall("ReadDirectoryChangesW","UInt",__[LP].hD,"UInt",__[LP].FNI[""],"UInt",sizeof_FNI ,"Int",__[LP].sD,"UInt",__[LP].CNG,"UInt",0,"UInt",__[LP].O[""],"UInt",0) timer:=DllCall("SetTimer","Uint",0,"UInt",timer,"Uint",50,"UInt",WatchDirectory) Return } Return } Changes: 18.02.2012 - AHKv2 version 05.09.2011 - Fixed OVERLAPED structure and _Struct 31.08.2011 - Updated to use new _Struct class 11.03.2011 - Fixed a bug for StrGet FileName (FNI.FileNameLength/2) 02.03.2011 - Fixed a bug for ANSI AHK_L 08.01.2011 - Fixed a bug in filtering option when * was used. - Fixed to report a change when a file is renamed and new or old filename do not match the filter. 12.11.2010 - Small bug fixes and a routine to reconnect network shared drives 11.11.2010 - Changed sizeof_FNI back to 65536 because a higher buffer seems to be not valid for network drives
Last edited by HotKeyIt on May 17th, 2012, 10:26 pm, edited 17 times in total.
|
|