zorphnog Posted May 12, 2008 Share Posted May 12, 2008 Good work on figuring it out guys. I have been playing around with the code as well, and have made a GUI for it. I simplified the different dll calls into some udfs so I thought I'd share it with anyone who might want it. expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.2.10.0 Author: zorphnog (M. Mims) Script Function: Monitors the user defined directories for file activity. #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <WinAPI.au3> #include <Date.au3> #include <GUIConstants.au3> #include <GuiListBox.au3> #include <GuiListView.au3> Global Const _ $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, _ $FILE_FLAG_OVERLAPPED = 0x40000000 Global Const _ $FILE_NOTIFY_CHANGE_ALL = 0x17F, _ $FILE_NOTIFY_CHANGE_FILE_NAME = 0x001, _ $FILE_NOTIFY_CHANGE_DIR_NAME = 0x002, _ $FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004, _ $FILE_NOTIFY_CHANGE_SIZE = 0x008, _ $FILE_NOTIFY_CHANGE_LAST_WRITE = 0x010, _ $FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020, _ $FILE_NOTIFY_CHANGE_CREATION = 0x040, _ $FILE_NOTIFY_CHANGE_SECURITY = 0x100 Global Const _ $FILE_ACTION_ADDED = 0x1, _ $FILE_ACTION_REMOVED = 0x2, _ $FILE_ACTION_MODIFIED = 0x3, _ $FILE_ACTION_RENAMED_OLD_NAME = 0x4, _ $FILE_ACTION_RENAMED_NEW_NAME = 0x5 Global Const _ $MWMO_ALERTABLE = 0x0002, _ $MWMO_INPUTAVAILABLE = 0x0004, _ $MWMO_WAITALL = 0x0001 Global Const $FILE_LIST_DIRECTORY = 0x0001 Global Const $QS_ALLINPUT = 0x04FF Global Const $INFINITE = 0xFFFF Global Const $tagFNIIncomplete = "dword NextEntryOffset;dword Action;dword FileNameLength" Global $bMonitorDone, $bSelected, $bMonitor AutoItSetOption("GUIOnEventMode", 1) $gFileMon = GUICreate("Directory Monitor", 731, 385, 194, 126) GUISetOnEvent($GUI_EVENT_CLOSE, "_OnEvent_Close") GUICtrlCreateGroup("Monitored Directories", 8, 0, 713, 105) $btAdd = GUICtrlCreateButton("Add", 16, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Add") $btRemove = GUICtrlCreateButton("Remove", 16, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Remove") GUICtrlSetState(-1, $GUI_DISABLE) $lbDirectories = GUICtrlCreateList("", 104, 16, 506, 71) $btMonitor = GUICtrlCreateButton("Start Monitor", 632, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Monitor") GUICtrlSetState(-1, $GUI_DISABLE) $btClear = GUICtrlCreateButton("Clear", 632, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Clear") GUICtrlCreateGroup("", -99, -99, 1, 1) $lvNotifications = GUICtrlCreateListView("Action|Time|File", 8, 112, 714, 262) GUICtrlSendMsg(-1, 0x101E, 0, Int(.1*710)) GUICtrlSendMsg(-1, 0x101E, 1, Int(.2*710)) GUICtrlSendMsg(-1, 0x101E, 2, Int(.7*710)-20) GUISetState(@SW_SHOW) _Main() Func _DisplayFileMessages($hBuffer, $sDir) Local $hFileNameInfo, $pBuffer, $hTime Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate($tagFNIIncomplete, $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength")/2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) $hTime = _Date_Time_GetSystemTime() Switch DllStructGetData($hFileNameInfo, "Action") Case $FILE_ACTION_ADDED _GUICtrlListView_InsertItem($lvNotifications, "Created", 0) Case $FILE_ACTION_REMOVED _GUICtrlListView_InsertItem($lvNotifications, "Deleted", 0) Case $FILE_ACTION_MODIFIED _GUICtrlListView_InsertItem($lvNotifications, "Modified", 0) Case $FILE_ACTION_RENAMED_OLD_NAME _GUICtrlListView_InsertItem($lvNotifications, "Rename-", 0) Case $FILE_ACTION_RENAMED_NEW_NAME _GUICtrlListView_InsertItem($lvNotifications, "Rename+", 0) Case Else _GUICtrlListView_InsertItem($lvNotifications, "Unknown", 0) EndSwitch _GUICtrlListView_AddSubItem($lvNotifications, 0, _Date_Time_SystemTimeToDateTimeStr($hTime), 1) _GUICtrlListView_AddSubItem($lvNotifications, 0, $sDir & DllStructGetData($hFileName, "FileName"), 2) $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc Func _GetBufferHandle () Return DllStructCreate("ubyte[2048]") EndFunc Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $bAsync = Default, $nTimeout = Default) Local $aMsg, $i, $nBytes = 0 If $nTimeout = -1 Or IsKeyword($nTimeout) Then $nTimeout = 250 If Not $bAsync Then $nTimeout = $INFINITE $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0, _ "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles)-1 If Not _WinAPI_GetOverlappedResult($aDirHandles[$i], DllStructGetPtr($aOverlapped[$i]), $nBytes, True) Then ConsoleWrite("!> GetOverlappedResult Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Return 0 EndIf DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _DisplayFileMessages($hBuffer, $aDirs[$i]) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i],False,True) Return $nBytes EndSwitch Return 0 EndFunc Func _GetDirHandle($sDir) Local $aResult $aResult = DllCall("Kernel32.dll", "hwnd", "CreateFile", _ "str", $sDir, _ "int", $FILE_LIST_DIRECTORY, _ "int", BitOR($FILE_SHARE_DELETE,$FILE_SHARE_READ,$FILE_SHARE_WRITE), _ "ptr", 0, _ "int", $OPEN_EXISTING, _ "int", BitOR($FILE_FLAG_BACKUP_SEMANTICS,$FILE_FLAG_OVERLAPPED), _ "int", 0) If $aResult[0] = 0 Then ConsoleWrite("!> CreateFile Error (" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func _GetEventHandles ($aOverlapped) Local $i, $hEvents $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $i=1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$i-1], "hEvent"), $i) Next Return $hEvents EndFunc Func _GetOverlappedHandle () Local $hOverlapped = DllStructCreate($tagOVERLAPPED) For $i=1 To 5 DllStructSetData($hOverlapped, $i, 0) Next Return $hOverlapped EndFunc Func _Main () $bSelected = False $bMonitorDone = True $bMonitor = False While 1 If Not $bMonitorDone Then _MonitorDirs() If $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) = 0 Then $bMonitor = Not $bMonitor GUICtrlSetState($btMonitor, $GUI_DISABLE) ElseIf Not $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) > 0 Then $bMonitor = Not $bMonitor GUICtrlSetState($btMonitor, $GUI_ENABLE) EndIf If $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) = -1 Then $bSelected = Not $bSelected GUICtrlSetState($btRemove, $GUI_DISABLE) ElseIf Not $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) <> -1 Then $bSelected = Not $bSelected GUICtrlSetState($btRemove, $GUI_ENABLE) EndIf WEnd EndFunc Func _MonitorDirs () Local $i, $nMax, $hBuffer, $hEvents $nMax = _GUICtrlListBox_GetCount($lbDirectories) Local $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] $hBuffer = _GetBufferHandle() For $i = 0 To $nMax-1 $aDirs[$i] = _GUICtrlListBox_GetText($lbDirectories, $i) $aDirHandles[$i] = _GetDirHandle($aDirs[$i]) $aOverlapped[$i] = _GetOverlappedHandle() _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, True) Next $hEvents = _GetEventHandles($aOverlapped) While Not $bMonitorDone _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs) WEnd EndFunc Func _OnEvent_Add () Local $sDir, $nMax, $i $sDir = FileSelectFolder("Select directory to monitor", "") If $sDir <> "" Then If StringRight($sDir, 1) <> "\" Then $sDir &= "\" $nMax = _GUICtrlListBox_GetCount($lbDirectories)-1 For $i = 0 To $nMax If _GUICtrlListBox_GetText($lbDirectories, $i) = $sDir Then Return Next _GUICtrlListBox_AddString($lbDirectories, $sDir) EndIf EndFunc Func _OnEvent_Clear () _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($lvNotifications)) EndFunc Func _OnEvent_Close () Exit EndFunc Func _OnEvent_Monitor () If $bMonitorDone Then $bMonitorDone = False GUICtrlSetData($btMonitor, "Stop Monitor") GUICtrlSetState($btAdd, $GUI_DISABLE) GUICtrlSetState($btRemove, $GUI_DISABLE) GUICtrlSetState($lbDirectories, $GUI_DISABLE) $bSelected = False Else $bMonitorDone = True GUICtrlSetState($lbDirectories, $GUI_ENABLE) GUICtrlSetState($btAdd, $GUI_ENABLE) GUICtrlSetData($btMonitor, "Start Monitor") EndIf EndFunc Func _OnEvent_Remove () _GUICtrlListBox_DeleteString($lbDirectories, _GUICtrlListBox_GetCurSel($lbDirectories)) EndFunc Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial = False, $bSubtree = False) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("Kernel32.dll", "hwnd", "CreateEvent", _ "uint", 0, _ "int", True, _ "int", False, _ "uint", 0) If $hEvent[0] = 0 Then ConsoleWrite("!> CreateEvent Failed (" & _WinAPI_GetLastError() & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf $aResult = DllCall("Kernel32.dll", "int", "ReadDirectoryChangesW", _ "hwnd", $hDir, _ "ptr", $pBuffer, _ "dword", $nBufferLength, _ "int", $bSubtree, _ "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, _ $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME), _ "uint", 0, _ "uint", $pOverlapped, _ "uint", 0) If $aResult[0] = 0 Then ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Link to comment Share on other sites More sharing options...
ptrex Posted May 13, 2008 Share Posted May 13, 2008 @all very nice script !! reagards, ptrex Contributions :Firewall Log Analyzer for XP - Creating COM objects without a need of DLL's - UPnP support in AU3Crystal Reports Viewer - PDFCreator in AutoIT - Duplicate File FinderSQLite3 Database functionality - USB Monitoring - Reading Excel using SQLRun Au3 as a Windows Service - File Monitor - Embedded Flash PlayerDynamic Functions - Control Panel Applets - Digital Signing Code - Excel Grid In AutoIT - Constants for Special Folders in WindowsRead data from Any Windows Edit Control - SOAP and Web Services in AutoIT - Barcode Printing Using PS - AU3 on LightTD WebserverMS LogParser SQL Engine in AutoIT - ImageMagick Image Processing - Converter @ Dec - Hex - Bin -Email Address Encoder - MSI Editor - SNMP - MIB ProtocolFinancial Functions UDF - Set ACL Permissions - Syntax HighLighter for AU3ADOR.RecordSet approach - Real OCR - HTTP Disk - PDF Reader Personal Worldclock - MS Indexing Engine - Printing ControlsGuiListView - Navigation (break the 4000 Limit barrier) - Registration Free COM DLL Distribution - Update - WinRM SMART Analysis - COM Object Browser - Excel PivotTable Object - VLC Media Player - Windows LogOnOff Gui -Extract Data from Outlook to Word & Excel - Analyze Event ID 4226 - DotNet Compiler Wrapper - Powershell_COM - New Link to comment Share on other sites More sharing options...
thomaatje Posted August 11, 2008 Share Posted August 11, 2008 (edited) Realy nice good job all I've been looking for a script like this for a while... Would it be possible to see what program edits/deletes/moves a file? Edited August 11, 2008 by Forsaken Link to comment Share on other sites More sharing options...
zorphnog Posted August 11, 2008 Share Posted August 11, 2008 Would it be possible to see what program edits/deletes/moves a file?Not with the method used in this script. The only information returned is what type of action took place. See http://msdn.microsoft.com/en-us/library/aa364391(VS.85).aspx, for more information about the FILE_NOTIFY_INFORMATION structure. Link to comment Share on other sites More sharing options...
thomaatje Posted August 11, 2008 Share Posted August 11, 2008 (edited) Not with the method used in this script. The only information returned is what type of action took place. See http://msdn.microsoft.com/en-us/library/aa364391(VS.85).aspx, for more information about the FILE_NOTIFY_INFORMATION structure.ThanksBut is there an other way for checking what program edits a file? Edited August 11, 2008 by Forsaken Link to comment Share on other sites More sharing options...
Dizzy Posted August 26, 2008 Share Posted August 26, 2008 Hi together, i stripped of "zorphnog's" GUI-Version and tried to install it as a service..... I can make the service ( sc screate Monitor binPath= <path to exe> ) but i can't start the service. Isn't it possible to make this as a service? CODE#cs ---------------------------------------------------------------------------- AutoIt Version: 3.2.10.0 Author: zorphnog (M. Mims) Script Function: Monitors the user defined directories for file activity. To Do : #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <WinAPI.au3> #include <Date.au3> HotKeySet("{ESC}", "CLOSE") $sDir = "C:\2\" Global Const _ $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, _ $FILE_FLAG_OVERLAPPED = 0x40000000 Global Const _ $FILE_NOTIFY_CHANGE_ALL = 0x17F, _ $FILE_NOTIFY_CHANGE_FILE_NAME = 0x001, _ $FILE_NOTIFY_CHANGE_DIR_NAME = 0x002, _ $FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004, _ $FILE_NOTIFY_CHANGE_SIZE = 0x008, _ $FILE_NOTIFY_CHANGE_LAST_WRITE = 0x010, _ $FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020, _ $FILE_NOTIFY_CHANGE_CREATION = 0x040, _ $FILE_NOTIFY_CHANGE_SECURITY = 0x100 Global Const _ $FILE_ACTION_ADDED = 0x1, _ $FILE_ACTION_REMOVED = 0x2, _ $FILE_ACTION_MODIFIED = 0x3, _ $FILE_ACTION_RENAMED_OLD_NAME = 0x4, _ $FILE_ACTION_RENAMED_NEW_NAME = 0x5 Global Const _ $MWMO_ALERTABLE = 0x0002, _ $MWMO_INPUTAVAILABLE = 0x0004, _ $MWMO_WAITALL = 0x0001 Global Const $FILE_LIST_DIRECTORY = 0x0001 Global Const $QS_ALLINPUT = 0x04FF Global Const $INFINITE = 0xFFFF Global Const $tagFNIIncomplete = "dword NextEntryOffset;dword Action;dword FileNameLength" Global $bMonitorDone, $bSelected, $bMonitor AutoItSetOption("GUIOnEventMode", 1) _Main() Func _DisplayFileMessages($hBuffer, $sDir) Local $hFileNameInfo, $pBuffer, $hTime Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate($tagFNIIncomplete, $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength")/2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) $hTime = _Date_Time_GetSystemTime() Switch DllStructGetData($hFileNameInfo, "Action") Case $FILE_ACTION_ADDED ConsoleWrite(" Created " ) If DllStructGetData($hFileName, "FileName") = "neu.txt" Then FileCopy($sDir & DllStructGetData($hFileName, "FileName"), $sdir & "gefunden.txt",1) EndIf Case $FILE_ACTION_REMOVED ConsoleWrite( " Deleted " ) Case $FILE_ACTION_MODIFIED ConsoleWrite(" Modified " ) Case $FILE_ACTION_RENAMED_OLD_NAME ConsoleWrite(" Rename- " ) Case $FILE_ACTION_RENAMED_NEW_NAME ConsoleWrite(" Rename+ " ) Case Else ConsoleWrite(" Unknown" ) EndSwitch ConsoleWrite(_Date_Time_SystemTimeToDateTimeStr($hTime)) ConsoleWrite(" : " & $sDir & DllStructGetData($hFileName, "FileName") & @crlf) $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc Func _GetBufferHandle () Return DllStructCreate("ubyte[2048]") EndFunc Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $bAsync = Default, $nTimeout = Default) Local $aMsg, $i, $nBytes = 0 If $nTimeout = -1 Or IsKeyword($nTimeout) Then $nTimeout = 250 If Not $bAsync Then $nTimeout = $INFINITE $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0, _ "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles)-1 If Not _WinAPI_GetOverlappedResult($aDirHandles[$i], DllStructGetPtr($aOverlapped[$i]), $nBytes, True) Then ConsoleWrite("!> GetOverlappedResult Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Return 0 EndIf DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _DisplayFileMessages($hBuffer, $aDirs[$i]) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i],False,True) Return $nBytes EndSwitch Return 0 EndFunc Func _GetDirHandle($sDir) Local $aResult $aResult = DllCall("Kernel32.dll", "hwnd", "CreateFile", _ "str", $sDir, _ "int", $FILE_LIST_DIRECTORY, _ "int", BitOR($FILE_SHARE_DELETE,$FILE_SHARE_READ,$FILE_SHARE_WRITE), _ "ptr", 0, _ "int", $OPEN_EXISTING, _ "int", BitOR($FILE_FLAG_BACKUP_SEMANTICS,$FILE_FLAG_OVERLAPPED), _ "int", 0) If $aResult[0] = 0 Then ConsoleWrite("!> CreateFile Error (" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func _GetEventHandles ($aOverlapped) Local $i, $hEvents $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $i=1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$i-1], "hEvent"), $i) Next Return $hEvents EndFunc Func _GetOverlappedHandle () Local $hOverlapped = DllStructCreate($tagOVERLAPPED) For $i=1 To 5 DllStructSetData($hOverlapped, $i, 0) Next Return $hOverlapped EndFunc Func _Main () $bSelected = True $bMonitorDone = False $bMonitor = True While 1 If Not $bMonitorDone Then _MonitorDirs() If $bMonitor Then $bMonitor = Not $bMonitor EndIf If $bSelected Then $bSelected = Not $bSelected EndIf WEnd EndFunc Func _MonitorDirs () Local $i, $nMax, $hBuffer, $hEvents $nMax = 1 Local $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] $hBuffer = _GetBufferHandle() For $i = 0 To $nMax-1 $aDirs[$i] = $sDir $aDirHandles[$i] = _GetDirHandle($aDirs[$i]) $aOverlapped[$i] = _GetOverlappedHandle() _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, True) Next $hEvents = _GetEventHandles($aOverlapped) While Not $bMonitorDone ; loop until "ESC" _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs) WEnd EndFunc Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial = False, $bSubtree = False) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("Kernel32.dll", "hwnd", "CreateEvent", _ "uint", 0, _ "int", True, _ "int", False, _ "uint", 0) If $hEvent[0] = 0 Then ConsoleWrite("!> CreateEvent Failed (" & _WinAPI_GetLastError() & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf $aResult = DllCall("Kernel32.dll", "int", "ReadDirectoryChangesW", _ "hwnd", $hDir, _ "ptr", $pBuffer, _ "dword", $nBufferLength, _ "int", $bSubtree, _ "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, _ $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME), _ "uint", 0, _ "uint", $pOverlapped, _ "uint", 0) If $aResult[0] = 0 Then ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func CLOSE() Exit EndFunc Greets Dizzy Link to comment Share on other sites More sharing options...
zorphnog Posted August 26, 2008 Share Posted August 26, 2008 (edited) I'm not sure what the requirements are to create a service application, but I would imagine the you would have to implement the correct hooks and handlers for the services API. I'm not sure that its possible to do with AutoIt.P.S. ConsoleWrite is not going to display your messages if you're running as a service. You probably want to write to a log file or publish it as an application event.edit - Actually, check out the FAQ sticky for information about creating service applications http://www.autoitscript.com/forum/index.php?showtopic=37289 Edited August 26, 2008 by zorphnog Link to comment Share on other sites More sharing options...
Dizzy Posted August 27, 2008 Share Posted August 27, 2008 I'm not sure what the requirements are to create a service application, but I would imagine the you would have to implement the correct hooks and handlers for the services API. I'm not sure that its possible to do with AutoIt.P.S. ConsoleWrite is not going to display your messages if you're running as a service. You probably want to write to a log file or publish it as an application event.edit - Actually, check out the FAQ sticky for information about creating service applications http://www.autoitscript.com/forum/index.php?showtopic=37289Hi zorphnog,thanks for your reply.Yes, i know that i don't see my console messages. This was just a first test to implement this as a service. Under "actions" you can see, that i look for a file neu.txt and if exist the program copies it to a new file. This is just a short function test. And thanks for the hint "creating service applications" - i'll have a look on it.Dizzy Link to comment Share on other sites More sharing options...
vcivilen Posted December 25, 2008 Share Posted December 25, 2008 I just create try Dizzy modified one, but it cannot run under service properly. Have any other solutions for it? Thanks, Link to comment Share on other sites More sharing options...
seesoe Posted March 3, 2009 Share Posted March 3, 2009 this is pretty neat, exactly what i wanted, i didn't think monitoring something would be so hard, i spent a good day trying to figure out a way to monitor a file or dir, and spent a while searching the forums. after messing around with quite a few different things i finally came access this thread, but i think it needs a little bit more proper posting.i take no credit for any work at all im just reposting the script, the following is a gui version of a program that will monitor what you selectthis was posted on page 4 by zorphnog - #520303expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.2.10.0 Author: zorphnog (M. Mims) Script Function: Monitors the user defined directories for file activity. #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <WinAPI.au3> #include <Date.au3> #include <GUIConstants.au3> #include <GuiListBox.au3> #include <GuiListView.au3> Global Const _ $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, _ $FILE_FLAG_OVERLAPPED = 0x40000000 Global Const _ $FILE_NOTIFY_CHANGE_ALL = 0x17F, _ $FILE_NOTIFY_CHANGE_FILE_NAME = 0x001, _ $FILE_NOTIFY_CHANGE_DIR_NAME = 0x002, _ $FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004, _ $FILE_NOTIFY_CHANGE_SIZE = 0x008, _ $FILE_NOTIFY_CHANGE_LAST_WRITE = 0x010, _ $FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020, _ $FILE_NOTIFY_CHANGE_CREATION = 0x040, _ $FILE_NOTIFY_CHANGE_SECURITY = 0x100 Global Const _ $FILE_ACTION_ADDED = 0x1, _ $FILE_ACTION_REMOVED = 0x2, _ $FILE_ACTION_MODIFIED = 0x3, _ $FILE_ACTION_RENAMED_OLD_NAME = 0x4, _ $FILE_ACTION_RENAMED_NEW_NAME = 0x5 Global Const _ $MWMO_ALERTABLE = 0x0002, _ $MWMO_INPUTAVAILABLE = 0x0004, _ $MWMO_WAITALL = 0x0001 Global Const $FILE_LIST_DIRECTORY = 0x0001 Global Const $QS_ALLINPUT = 0x04FF Global Const $INFINITE = 0xFFFF Global Const $tagFNIIncomplete = "dword NextEntryOffset;dword Action;dword FileNameLength" Global $bMonitorDone, $bSelected, $bMonitor AutoItSetOption("GUIOnEventMode", 1) $gFileMon = GUICreate("Directory Monitor", 731, 385, 194, 126) GUISetOnEvent($GUI_EVENT_CLOSE, "_OnEvent_Close") GUICtrlCreateGroup("Monitored Directories", 8, 0, 713, 105) $btAdd = GUICtrlCreateButton("Add", 16, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Add") $btRemove = GUICtrlCreateButton("Remove", 16, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Remove") GUICtrlSetState(-1, $GUI_DISABLE) $lbDirectories = GUICtrlCreateList("", 104, 16, 506, 71) $btMonitor = GUICtrlCreateButton("Start Monitor", 632, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Monitor") GUICtrlSetState(-1, $GUI_DISABLE) $btClear = GUICtrlCreateButton("Clear", 632, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Clear") GUICtrlCreateGroup("", -99, -99, 1, 1) $lvNotifications = GUICtrlCreateListView("Action|Time|File", 8, 112, 714, 262) GUICtrlSendMsg(-1, 0x101E, 0, Int(.1*710)) GUICtrlSendMsg(-1, 0x101E, 1, Int(.2*710)) GUICtrlSendMsg(-1, 0x101E, 2, Int(.7*710)-20) GUISetState(@SW_SHOW) _Main() Func _DisplayFileMessages($hBuffer, $sDir) Local $hFileNameInfo, $pBuffer, $hTime Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate($tagFNIIncomplete, $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength")/2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) $hTime = _Date_Time_GetSystemTime() Switch DllStructGetData($hFileNameInfo, "Action") Case $FILE_ACTION_ADDED _GUICtrlListView_InsertItem($lvNotifications, "Created", 0) Case $FILE_ACTION_REMOVED _GUICtrlListView_InsertItem($lvNotifications, "Deleted", 0) Case $FILE_ACTION_MODIFIED _GUICtrlListView_InsertItem($lvNotifications, "Modified", 0) Case $FILE_ACTION_RENAMED_OLD_NAME _GUICtrlListView_InsertItem($lvNotifications, "Rename-", 0) Case $FILE_ACTION_RENAMED_NEW_NAME _GUICtrlListView_InsertItem($lvNotifications, "Rename+", 0) Case Else _GUICtrlListView_InsertItem($lvNotifications, "Unknown", 0) EndSwitch _GUICtrlListView_AddSubItem($lvNotifications, 0, _Date_Time_SystemTimeToDateTimeStr($hTime), 1) _GUICtrlListView_AddSubItem($lvNotifications, 0, $sDir & DllStructGetData($hFileName, "FileName"), 2) $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc Func _GetBufferHandle () Return DllStructCreate("ubyte[2048]") EndFunc Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $bAsync = Default, $nTimeout = Default) Local $aMsg, $i, $nBytes = 0 If $nTimeout = -1 Or IsKeyword($nTimeout) Then $nTimeout = 250 If Not $bAsync Then $nTimeout = $INFINITE $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0, _ "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles)-1 If Not _WinAPI_GetOverlappedResult($aDirHandles[$i], DllStructGetPtr($aOverlapped[$i]), $nBytes, True) Then ConsoleWrite("!> GetOverlappedResult Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Return 0 EndIf DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _DisplayFileMessages($hBuffer, $aDirs[$i]) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i],False,True) Return $nBytes EndSwitch Return 0 EndFunc Func _GetDirHandle($sDir) Local $aResult $aResult = DllCall("Kernel32.dll", "hwnd", "CreateFile", _ "str", $sDir, _ "int", $FILE_LIST_DIRECTORY, _ "int", BitOR($FILE_SHARE_DELETE,$FILE_SHARE_READ,$FILE_SHARE_WRITE), _ "ptr", 0, _ "int", $OPEN_EXISTING, _ "int", BitOR($FILE_FLAG_BACKUP_SEMANTICS,$FILE_FLAG_OVERLAPPED), _ "int", 0) If $aResult[0] = 0 Then ConsoleWrite("!> CreateFile Error (" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func _GetEventHandles ($aOverlapped) Local $i, $hEvents $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $i=1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$i-1], "hEvent"), $i) Next Return $hEvents EndFunc Func _GetOverlappedHandle () Local $hOverlapped = DllStructCreate($tagOVERLAPPED) For $i=1 To 5 DllStructSetData($hOverlapped, $i, 0) Next Return $hOverlapped EndFunc Func _Main () $bSelected = False $bMonitorDone = True $bMonitor = False While 1 If Not $bMonitorDone Then _MonitorDirs() If $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) = 0 Then $bMonitor = Not $bMonitor GUICtrlSetState($btMonitor, $GUI_DISABLE) ElseIf Not $bMonitor And _GUICtrlListBox_GetCount($lbDirectories) > 0 Then $bMonitor = Not $bMonitor GUICtrlSetState($btMonitor, $GUI_ENABLE) EndIf If $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) = -1 Then $bSelected = Not $bSelected GUICtrlSetState($btRemove, $GUI_DISABLE) ElseIf Not $bSelected And _GUICtrlListBox_GetCurSel($lbDirectories) <> -1 Then $bSelected = Not $bSelected GUICtrlSetState($btRemove, $GUI_ENABLE) EndIf WEnd EndFunc Func _MonitorDirs () Local $i, $nMax, $hBuffer, $hEvents $nMax = _GUICtrlListBox_GetCount($lbDirectories) Local $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] $hBuffer = _GetBufferHandle() For $i = 0 To $nMax-1 $aDirs[$i] = _GUICtrlListBox_GetText($lbDirectories, $i) $aDirHandles[$i] = _GetDirHandle($aDirs[$i]) $aOverlapped[$i] = _GetOverlappedHandle() _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, True) Next $hEvents = _GetEventHandles($aOverlapped) While Not $bMonitorDone _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs) WEnd EndFunc Func _OnEvent_Add () Local $sDir, $nMax, $i $sDir = FileSelectFolder("Select directory to monitor", "") If $sDir <> "" Then If StringRight($sDir, 1) <> "\" Then $sDir &= "\" $nMax = _GUICtrlListBox_GetCount($lbDirectories)-1 For $i = 0 To $nMax If _GUICtrlListBox_GetText($lbDirectories, $i) = $sDir Then Return Next _GUICtrlListBox_AddString($lbDirectories, $sDir) EndIf EndFunc Func _OnEvent_Clear () _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($lvNotifications)) EndFunc Func _OnEvent_Close () Exit EndFunc Func _OnEvent_Monitor () If $bMonitorDone Then $bMonitorDone = False GUICtrlSetData($btMonitor, "Stop Monitor") GUICtrlSetState($btAdd, $GUI_DISABLE) GUICtrlSetState($btRemove, $GUI_DISABLE) GUICtrlSetState($lbDirectories, $GUI_DISABLE) $bSelected = False Else $bMonitorDone = True GUICtrlSetState($lbDirectories, $GUI_ENABLE) GUICtrlSetState($btAdd, $GUI_ENABLE) GUICtrlSetData($btMonitor, "Start Monitor") EndIf EndFunc Func _OnEvent_Remove () _GUICtrlListBox_DeleteString($lbDirectories, _GUICtrlListBox_GetCurSel($lbDirectories)) EndFunc Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial = False, $bSubtree = False) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("Kernel32.dll", "hwnd", "CreateEvent", _ "uint", 0, _ "int", True, _ "int", False, _ "uint", 0) If $hEvent[0] = 0 Then ConsoleWrite("!> CreateEvent Failed (" & _WinAPI_GetLastError() & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf $aResult = DllCall("Kernel32.dll", "int", "ReadDirectoryChangesW", _ "hwnd", $hDir, _ "ptr", $pBuffer, _ "dword", $nBufferLength, _ "int", $bSubtree, _ "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, _ $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME), _ "uint", 0, _ "uint", $pOverlapped, _ "uint", 0) If $aResult[0] = 0 Then ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFuncoÝ÷ Úz0¶¢YhÂ)à±Êâ¦×·¦{hÊ«£ ìr¸©µ»ë-r§)ජ{(ì+×¥w¬¶!jܨ»§¶Ú!j^í«^½éíj¢+Zéèr·×è®Ø^±Êâ¦Ø¦ë-êh²Ø§+m+/z»"¢x¬¶¬jg±·¢·ºÜ"¶èè¬r¸©µ¼hopes this helps people out, its a great script:) thanks all!cheersseesoe Link to comment Share on other sites More sharing options...
Digisoul Posted March 5, 2009 Share Posted March 5, 2009 @ seesoe Why the GUI version always give me error when i trying to re monitor any location ? is it a bug ? 73 108 111 118 101 65 117 116 111 105 116 Link to comment Share on other sites More sharing options...
Recce Posted March 28, 2009 Share Posted March 28, 2009 Thank you seesoe. This is what I need also. But how to add more files/folders? I can see that it is this string: $sDir = "C:\1\" But how? expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.2.10.0 Author: zorphnog (M. Mims) Script Function: Monitors the user defined directories for file activity. To Do : #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <WinAPI.au3> #include <Date.au3> HotKeySet("{ESC}", "CLOSE") $sDir = "C:\1\" Global Const _ $FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, _ $FILE_FLAG_OVERLAPPED = 0x40000000 Global Const _ $FILE_NOTIFY_CHANGE_ALL = 0x17F, _ $FILE_NOTIFY_CHANGE_FILE_NAME = 0x001, _ $FILE_NOTIFY_CHANGE_DIR_NAME = 0x002, _ $FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x004, _ $FILE_NOTIFY_CHANGE_SIZE = 0x008, _ $FILE_NOTIFY_CHANGE_LAST_WRITE = 0x010, _ $FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x020, _ $FILE_NOTIFY_CHANGE_CREATION = 0x040, _ $FILE_NOTIFY_CHANGE_SECURITY = 0x100 Global Const _ $FILE_ACTION_ADDED = 0x1, _ $FILE_ACTION_REMOVED = 0x2, _ $FILE_ACTION_MODIFIED = 0x3, _ $FILE_ACTION_RENAMED_OLD_NAME = 0x4, _ $FILE_ACTION_RENAMED_NEW_NAME = 0x5 Global Const _ $MWMO_ALERTABLE = 0x0002, _ $MWMO_INPUTAVAILABLE = 0x0004, _ $MWMO_WAITALL = 0x0001 Global Const $FILE_LIST_DIRECTORY = 0x0001 Global Const $QS_ALLINPUT = 0x04FF Global Const $INFINITE = 0xFFFF Global Const $tagFNIIncomplete = "dword NextEntryOffset;dword Action;dword FileNameLength" Global $bMonitorDone, $bSelected, $bMonitor AutoItSetOption("GUIOnEventMode", 1) _Main() Func _DisplayFileMessages($hBuffer, $sDir) Local $hFileNameInfo, $pBuffer, $hTime Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate($tagFNIIncomplete, $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength")/2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) $hTime = _Date_Time_GetSystemTime() Switch DllStructGetData($hFileNameInfo, "Action") Case $FILE_ACTION_ADDED ConsoleWrite(" Created " ) If DllStructGetData($hFileName, "FileName") = "neu.txt" Then FileCopy($sDir & DllStructGetData($hFileName, "FileName"), $sdir & "gefunden.txt",1) EndIf Case $FILE_ACTION_REMOVED MsgBox("","test","Deleted") ; ConsoleWrite( " Deleted " ) Case $FILE_ACTION_MODIFIED MsgBox('',"changed","something was changed in a file") ConsoleWrite(" Modified " ) Case $FILE_ACTION_RENAMED_OLD_NAME ConsoleWrite(" Rename- " ) Case $FILE_ACTION_RENAMED_NEW_NAME ConsoleWrite(" Rename+ " ) Case Else ConsoleWrite(" Unknown" ) EndSwitch ConsoleWrite(_Date_Time_SystemTimeToDateTimeStr($hTime)) ConsoleWrite(" : " & $sDir & DllStructGetData($hFileName, "FileName") & @crlf) $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc Func _GetBufferHandle () Return DllStructCreate("ubyte[2048]") EndFunc Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $bAsync = Default, $nTimeout = Default) Local $aMsg, $i, $nBytes = 0 If $nTimeout = -1 Or IsKeyword($nTimeout) Then $nTimeout = 250 If Not $bAsync Then $nTimeout = $INFINITE $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0, _ "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles)-1 If Not _WinAPI_GetOverlappedResult($aDirHandles[$i], DllStructGetPtr($aOverlapped[$i]), $nBytes, True) Then ConsoleWrite("!> GetOverlappedResult Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Return 0 EndIf DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _DisplayFileMessages($hBuffer, $aDirs[$i]) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i],False,True) Return $nBytes EndSwitch Return 0 EndFunc Func _GetDirHandle($sDir) Local $aResult $aResult = DllCall("Kernel32.dll", "hwnd", "CreateFile", _ "str", $sDir, _ "int", $FILE_LIST_DIRECTORY, _ "int", BitOR($FILE_SHARE_DELETE,$FILE_SHARE_READ,$FILE_SHARE_WRITE), _ "ptr", 0, _ "int", $OPEN_EXISTING, _ "int", BitOR($FILE_FLAG_BACKUP_SEMANTICS,$FILE_FLAG_OVERLAPPED), _ "int", 0) If $aResult[0] = 0 Then ConsoleWrite("!> CreateFile Error (" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func _GetEventHandles ($aOverlapped) Local $i, $hEvents $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $i=1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$i-1], "hEvent"), $i) Next Return $hEvents EndFunc Func _GetOverlappedHandle () Local $hOverlapped = DllStructCreate($tagOVERLAPPED) For $i=1 To 5 DllStructSetData($hOverlapped, $i, 0) Next Return $hOverlapped EndFunc Func _Main () $bSelected = True $bMonitorDone = False $bMonitor = True While 1 If Not $bMonitorDone Then _MonitorDirs() If $bMonitor Then $bMonitor = Not $bMonitor EndIf If $bSelected Then $bSelected = Not $bSelected EndIf WEnd EndFunc Func _MonitorDirs () Local $i, $nMax, $hBuffer, $hEvents $nMax = 1 Local $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] $hBuffer = _GetBufferHandle() For $i = 0 To $nMax-1 $aDirs[$i] = $sDir $aDirHandles[$i] = _GetDirHandle($aDirs[$i]) $aOverlapped[$i] = _GetOverlappedHandle() _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, True) Next $hEvents = _GetEventHandles($aOverlapped) While Not $bMonitorDone ; loop until "ESC" _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs) WEnd EndFunc Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial = False, $bSubtree = False) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("Kernel32.dll", "hwnd", "CreateEvent", _ "uint", 0, _ "int", True, _ "int", False, _ "uint", 0) If $hEvent[0] = 0 Then ConsoleWrite("!> CreateEvent Failed (" & _WinAPI_GetLastError() & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf $aResult = DllCall("Kernel32.dll", "int", "ReadDirectoryChangesW", _ "hwnd", $hDir, _ "ptr", $pBuffer, _ "dword", $nBufferLength, _ "int", $bSubtree, _ "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, _ $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME), _ "uint", 0, _ "uint", $pOverlapped, _ "uint", 0) If $aResult[0] = 0 Then ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc Func CLOSE() Exit EndFunc Link to comment Share on other sites More sharing options...
dmob Posted April 30, 2009 Share Posted April 30, 2009 (edited) Thank you seesoe. This is what I need also. But how to add more files/folders? I can see that it is this string: $sDir = "C:\1\" But how?Your answer is here "Just remember to set the $dirs variable to how many your going to watch, and then fill in the array from 0 to $dirs - 1 with the names of the directories (ending with a \ I believe)." Edited April 30, 2009 by dmob Link to comment Share on other sites More sharing options...
WeMartiansAreFriendly Posted July 4, 2009 Share Posted July 4, 2009 (edited) @all, Works great! I'm monitoring the c:\ drive with 'zorphnog' version and it seems to be catching everything without noticeable issues.. You should submit this to the Example Scripts forum so this can get more attention. (I only found this from KaFus signature. ) Edited July 4, 2009 by Kastout Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet() Link to comment Share on other sites More sharing options...
KpKrishnamoorthy Posted July 16, 2009 Share Posted July 16, 2009 Extremely nice script, works very well for me. I needed to monitor a network UNC path to figure out when new builds were pushed, and take certain actions based on file updates - this works brilliantly. Thanks to all the guys who worked on it! Kp. Link to comment Share on other sites More sharing options...
Heron Posted October 23, 2009 Share Posted October 23, 2009 Hi there, thanks for all who worked on this script to get it working. I was looking for something like this and could very well use it (be it that I broke it down to handle just one folder). One thing noted: when stopping and resuming the script, often it will crash. I tried to cleanup the event and struct variables but that didn't help. Finally I found that calling WinAPI CloseHandle() for the directory- and eventhandler did the job. Now monitoring can be stopped and resumed as much as you like. Just wanted to share this with you. - Heron - Link to comment Share on other sites More sharing options...
gr8BigGeek Posted January 19, 2010 Share Posted January 19, 2010 Hi there, thanks for all who worked on this script to get it working. I was looking for something like this and could very well use it (be it that I broke it down to handle just one folder). One thing noted: when stopping and resuming the script, often it will crash. I tried to cleanup the event and struct variables but that didn't help. Finally I found that calling WinAPI CloseHandle() for the directory- and eventhandler did the job. Now monitoring can be stopped and resumed as much as you like. Just wanted to share this with you. - Heron - I too have been checking out this au3 app and have been having a lot of fun with it. I was wondering if anyone knew how to modify a few things. I was attempting to accomplish the following: Pop-up window when an item entered into a certain folder (as a notifier) Minimize the application so it runs as a little icon by the icon tray next to the clock (and keeps running/monitoring the predetermined folder). Has the ability to be brought back into "normal" view if you right click the icon and select "maximize" or some such word. I have found stand alone "popup" and "minimize" au3 doc's on the forums but I don't know how to work them into this one. I've been linking them by inserting run("popup.exe", "", @SW_SHOW) but there is lag time when I do that. I would like to have it all run together. The purpose behind all of this: If you set your printer (on Windows XP) to "Print to Text" the only option it gives you is to print as the same file ex. DOC.txt I am acting as the router for our office and all of the printed documents DO NOT need to be printed and they come in at times in rapid succession and when my program is hanging up the newest print document writes over the last one and I completely miss a document! I'm trying to get it so that when the DOC.txt arrives in the predesignated folder my program automatically time/date stamps it with a unique number, sends me audio noises and visual notification that I have a new DOC.txt that has been received (and renamed) for me in the print folder I'm monitoring. Also, the "ZMV Monitor.au3" will not run unless you have "C:\print\INCOMING\" because it is set to monitor that location. When it finds that location does not exist it stops trying and closes out. I hope this makes sense. I'll attach all of the different coding I've been working on and if anyone could help me that would be wonderful!! Thank you so much in advance! Matt ZMV Monitor.au3 rename.au3 popup.au3 Link to comment Share on other sites More sharing options...
gr8BigGeek Posted January 19, 2010 Share Posted January 19, 2010 I forgot to add one other thing I was trying to do. I was also trying to see just the file name not the "C:\print\INCOMING\" (or the directory). This because I have the file being changed to a date/time stamp and scrolling over to see which is which is cumbersome. I also failed to attach this other one as well; sorry mates. Matt MINIMIZE TEST.au3 Link to comment Share on other sites More sharing options...
jackchen Posted August 15, 2010 Share Posted August 15, 2010 (edited) Good work on figuring it out guys. I have been playing around with the code as well, and have made a GUI for it. I simplified the different dll calls into some udfs so I thought I'd share it with anyone who might want it. This script drives my CPU up to 100%.I do need this functionality, so I tried to modify those scripts myself. According to http://msdn.microsoft.com/en-us/library/ms684245%28VS.85%29.aspx,if change these lines: $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0, _ "dword", 0x6) to: $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", _ "dword", UBound($aOverlapped), _ "ptr", DllStructGetPtr($hEvents), _ "dword", $nTimeout, _ "dword", 0x4FF, _ "dword", 0x6) The script will not be resource-consuming. And we should do some cleaning and close handles when stopping monitoring, thus the monitor can stop and restart without crash. I've developed a UDF _MonitorDirectory() for filesystem monitoring, the function with an example as below: expandcollapse popup;~ Example OnAutoItExitRegister("_Exit") Global $aDirs[2] $aDirs[0] = @ScriptDir $aDirs[1] = "C:\" _MonitorDirectory($aDirs, True, 100, "_ReportFileChanges") While 1 Sleep(20) WEnd ;~ This function will be called when changes are registered Func _ReportFileChanges($Action, $FilePath) ;~ Your own script here ... ;~ ... ConsoleWrite($Action & ": " & $FilePath & @CRLF) TrayTip("MonitorDirectory", $Action & ": " & $FilePath, 5, 1) EndFunc ;==>_ReportFileChanges ;~ Stop monitoring before exiting at least Func _Exit() _MonitorDirectory() Exit EndFunc ;==>_Quit ;~ =========================== FUNCTION _MonitorDirectory() ============================== #cs Description: Monitors the user defined directories for file activity. Original: http://www.autoitscript.com/forum/index.php?showtopic=69044&hl=folderspy&st=0 Modified: Jack Chen Syntax: _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges") Parameters: $Dirs - Optional: Zero-based array of valid directories to be monitored. $Subtree - Optional: Subtrees will be monitored if $Subtree = True. $TimerMs - Optional: Timer to register changes in milliseconds. $Function - Optional: Function to launch when changes are registered. e.g. _ReportChanges Syntax of your function must be e.g._ReportChanges($Action, $FilePath) Possible actions: Created, Deleted, Modified, Rename-, Rename+, Unknown Remarks: Call _MonitorDirectory() without parameters to stop monitoring all directories. THIS SHOULD BE DONE BEFORE EXITING SCRIPT AT LEAST. #ce Func _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges") Local Static $nMax, $hBuffer, $hEvents, $aSubtree, $sFunction If IsArray($Dirs) Then $nMax = UBound($Dirs) ElseIf $nMax < 1 Then Return EndIf Local Static $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] If IsArray($Dirs) Then $aDirs = $Dirs $aSubtree = $Subtree $sFunction = $Function ;~ $hBuffer = DllStructCreate("byte[4096]") $hBuffer = DllStructCreate("byte[65536]") For $i = 0 To $nMax - 1 If StringRight($aDirs[$i], 1) <> "\" Then $aDirs[$i] &= "\" ;~ http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx $aResult = DllCall("kernel32.dll", "hwnd", "CreateFile", "Str", $aDirs[$i], "Int", 0x1, "Int", BitOR(0x1, 0x4, 0x2), "ptr", 0, "int", 0x3, "int", BitOR(0x2000000, 0x40000000), "int", 0) $aDirHandles[$i] = $aResult[0] $aOverlapped[$i] = DllStructCreate("ulong_ptr Internal;ulong_ptr InternalHigh;dword Offset;dword OffsetHigh;handle hEvent") For $j = 1 To 5 DllStructSetData($aOverlapped, $j, 0) Next _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, $aSubtree) Next $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $j = 1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$j - 1], "hEvent"), $j) Next AdlibRegister("_GetChanges", $TimerMs) ElseIf $Dirs = "ReadDirChanges" Then _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction) ElseIf $Dirs = "" Then AdlibUnRegister("_GetChanges") ;~ Close Handle For $i = 0 To $nMax - 1 DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aDirHandles[$i]) DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aOverlapped[$i]) Next DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hEvents) $nMax = 0 $hBuffer = "" $hEvents = "" $aDirHandles = "" $aOverlapped = "" $aDirs = "" $aSubtree = "" $sFunction = "" EndIf EndFunc ;==>_MonitorDirectory Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial, $bSubtree) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("kernel32.dll", "hwnd", "CreateEvent", "UInt", 0, "Int", True, "Int", False, "UInt", 0) DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf ;~ http://msdn.microsoft.com/en-us/library/aa365465%28VS.85%29.aspx $aResult = DllCall("kernel32.dll", "Int", "ReadDirectoryChangesW", "hwnd", $hDir, "ptr", $pBuffer, "dword", $nBufferLength, "int", $bSubtree, "dword", BitOR(0x1, 0x2, 0x4, 0x8, 0x10, 0x40, 0x100), "Uint", 0, "Uint", $pOverlapped, "Uint", 0) Return $aResult[0] EndFunc ;==>_SetReadDirectory Func _GetChanges() _MonitorDirectory("ReadDirChanges") EndFunc ;==>_GetChanges Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction) Local $aMsg, $i, $nBytes = 0 $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", "dword", UBound($aOverlapped), "ptr", DllStructGetPtr($hEvents), "dword", -1, "dword", 0x4FF, "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles) - 1 DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _ParseFileMessages($hBuffer, $aDirs[$i], $sFunction) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], False, $aSubtree) Return $nBytes EndSwitch Return 0 EndFunc ;==>_GetDirectoryChanges Func _ParseFileMessages($hBuffer, $sDir, $sFunction) Local $hFileNameInfo, $pBuffer, $FilePath Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate("dword NextEntryOffset;dword Action;dword FileNameLength", $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength") / 2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) Switch DllStructGetData($hFileNameInfo, "Action") Case 0x1 ; $FILE_ACTION_ADDED $Action = "Created" Case 0x2 ; $FILE_ACTION_REMOVED $Action = "Deleted" Case 0x3 ; $FILE_ACTION_MODIFIED $Action = "Modified" Case 0x4 ; $FILE_ACTION_RENAMED_OLD_NAME $Action = "Rename-" Case 0x5 ; $FILE_ACTION_RENAMED_NEW_NAME $Action = "Rename+" Case Else $Action = "Unknown" EndSwitch $FilePath = $sDir & DllStructGetData($hFileName, "FileName") Call($sFunction, $Action, $FilePath) ; Launch the specified function $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc ;==>_ParseFileMessages ;~ ===========================End of FUNCTION _MonitorDirectory() ============================== I have modified zorphnog's FolderSpy with this function _MonitorDirectory().Now it's light and reliable. Code: expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.6.1 Author: zorphnog (M. Mims) Modified: Jackchen Script Function: Monitors the user defined directories for file activity. #ce ---------------------------------------------------------------------------- #include <Constants.au3> #include <WinAPI.au3> #include <Date.au3> #include <GUIConstants.au3> #include <GuiListBox.au3> #include <GuiListView.au3> #include <Array.au3> Global $bMonitoring = False AutoItSetOption("GUIOnEventMode", 1) $gFileMon = GUICreate("Directory Monitor", 731, 385, 194, 126) GUISetOnEvent($GUI_EVENT_CLOSE, "_OnEvent_Close") GUICtrlCreateGroup("Monitored Directories", 8, 0, 713, 105) $btAdd = GUICtrlCreateButton("Add", 16, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Add") $btRemove = GUICtrlCreateButton("Remove", 16, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Remove") GUICtrlSetState(-1, $GUI_DISABLE) $lbDirectories = GUICtrlCreateList("", 104, 16, 506, 71) $btMonitor = GUICtrlCreateButton("Start Monitor", 632, 24, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Monitor") GUICtrlSetState(-1, $GUI_DISABLE) $btClear = GUICtrlCreateButton("Clear", 632, 56, 75, 25, 0) GUICtrlSetOnEvent(-1, "_OnEvent_Clear") GUICtrlCreateGroup("", -99, -99, 1, 1) $lvNotifications = GUICtrlCreateListView("Action|Time|File", 8, 112, 714, 262) GUICtrlSendMsg(-1, 0x101E, 0, Int(.1 * 710)) GUICtrlSendMsg(-1, 0x101E, 1, Int(.2 * 710)) GUICtrlSendMsg(-1, 0x101E, 2, Int(.7 * 710) - 20) GUISetState(@SW_SHOW) While 1 If Not $bMonitoring And _GUICtrlListBox_GetCurSel($lbDirectories) <> -1 And GUICtrlGetState($btRemove) = $GUI_SHOW + $GUI_DISABLE Then GUICtrlSetState($btRemove, $GUI_ENABLE) EndIf Sleep(20) WEnd Func _ReportChanges($Action, $FilePath) Local $hTime $hTime = _Date_Time_GetSystemTime() _GUICtrlListView_InsertItem($lvNotifications, $Action, 0) _GUICtrlListView_AddSubItem($lvNotifications, 0, _Date_Time_SystemTimeToDateTimeStr($hTime), 1) _GUICtrlListView_AddSubItem($lvNotifications, 0, $FilePath, 2) EndFunc ;==>_ReportChanges Func _OnEvent_Add() Local $sDir, $nMax, $i $sDir = FileSelectFolder("Select directory to monitor", "") If $sDir <> "" Then If StringRight($sDir, 1) <> "\" Then $sDir &= "\" $nMax = _GUICtrlListBox_GetCount($lbDirectories) - 1 For $i = 0 To $nMax If _GUICtrlListBox_GetText($lbDirectories, $i) = $sDir Then Return Next _GUICtrlListBox_AddString($lbDirectories, $sDir) GUICtrlSetState($btMonitor, $GUI_ENABLE) EndIf EndFunc ;==>_OnEvent_Add Func _OnEvent_Clear() _GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($lvNotifications)) EndFunc ;==>_OnEvent_Clear Func _OnEvent_Close() If $bMonitoring Then _MonitorDirectory() Exit EndFunc ;==>_OnEvent_Close Func _OnEvent_Monitor() If Not $bMonitoring Then $bMonitoring = True GUICtrlSetData($btMonitor, "Stop Monitor") GUICtrlSetState($btAdd, $GUI_DISABLE) GUICtrlSetState($btRemove, $GUI_DISABLE) GUICtrlSetState($lbDirectories, $GUI_DISABLE) $n = _GUICtrlListBox_GetCount($lbDirectories) Local $Dirs[$n] For $i = 0 To $n - 1 $Dirs[$i] = _GUICtrlListBox_GetText($lbDirectories, $i) Next _MonitorDirectory($Dirs) Else $bMonitoring = False GUICtrlSetState($lbDirectories, $GUI_ENABLE) GUICtrlSetState($btAdd, $GUI_ENABLE) GUICtrlSetData($btMonitor, "Start Monitor") _MonitorDirectory() EndIf EndFunc ;==>_OnEvent_Monitor Func _OnEvent_Remove() _GUICtrlListBox_DeleteString($lbDirectories, _GUICtrlListBox_GetCurSel($lbDirectories)) If _GUICtrlListBox_GetCount($lbDirectories) = 0 Then GUICtrlSetState($btMonitor, $GUI_DISABLE) EndIf EndFunc ;==>_OnEvent_Remove ;~ =========================== FUNCTION _MonitorDirectory() ============================== #cs Description: Monitors the user defined directories for file activity. Original: http://www.autoitscript.com/forum/index.php?showtopic=69044&hl=folderspy&st=0 Modified: Jack Chen Syntax: _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges") Parameters: $Dirs - Optional: Zero-based array of valid directories to be monitored. $Subtree - Optional: Subtrees will be monitored if $Subtree = True. $TimerMs - Optional: Timer to register changes in milliseconds. $Function - Optional: Function to launch when changes are registered. e.g. _ReportChanges Syntax of your function must be e.g._ReportChanges($Action, $FilePath) Possible actions: Created, Deleted, Modified, Rename-, Rename+, Unknown Remarks: Call _MonitorDirectory() without parameters to stop monitoring all directories. THIS SHOULD BE DONE BEFORE EXITING SCRIPT AT LEAST. #ce Func _MonitorDirectory($Dirs = "", $Subtree = True, $TimerMs = 250, $Function = "_ReportChanges") Local Static $nMax, $hBuffer, $hEvents, $aSubtree, $sFunction If IsArray($Dirs) Then $nMax = UBound($Dirs) ElseIf $nMax < 1 Then Return EndIf Local Static $aDirHandles[$nMax], $aOverlapped[$nMax], $aDirs[$nMax] If IsArray($Dirs) Then $aDirs = $Dirs $aSubtree = $Subtree $sFunction = $Function ;~ $hBuffer = DllStructCreate("byte[4096]") $hBuffer = DllStructCreate("byte[65536]") For $i = 0 To $nMax - 1 If StringRight($aDirs[$i], 1) <> "\" Then $aDirs[$i] &= "\" ;~ http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx $aResult = DllCall("kernel32.dll", "hwnd", "CreateFile", "Str", $aDirs[$i], "Int", 0x1, "Int", BitOR(0x1, 0x4, 0x2), "ptr", 0, "int", 0x3, "int", BitOR(0x2000000, 0x40000000), "int", 0) $aDirHandles[$i] = $aResult[0] $aOverlapped[$i] = DllStructCreate("ulong_ptr Internal;ulong_ptr InternalHigh;dword Offset;dword OffsetHigh;handle hEvent") For $j = 1 To 5 DllStructSetData($aOverlapped, $j, 0) Next _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], True, $aSubtree) Next $hEvents = DllStructCreate("hwnd hEvent[" & UBound($aOverlapped) & "]") For $j = 1 To UBound($aOverlapped) DllStructSetData($hEvents, "hEvent", DllStructGetData($aOverlapped[$j - 1], "hEvent"), $j) Next AdlibRegister("_GetChanges", $TimerMs) ElseIf $Dirs = "ReadDirChanges" Then _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction) ElseIf $Dirs = "" Then AdlibUnRegister("_GetChanges") ;~ Close Handle For $i = 0 To $nMax - 1 DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aDirHandles[$i]) DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $aOverlapped[$i]) Next DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hEvents) $nMax = 0 $hBuffer = "" $hEvents = "" $aDirHandles = "" $aOverlapped = "" $aDirs = "" $aSubtree = "" $sFunction = "" EndIf EndFunc ;==>_MonitorDirectory Func _SetReadDirectory($hDir, $hBuffer, $hOverlapped, $bInitial, $bSubtree) Local $hEvent, $pBuffer, $nBufferLength, $pOverlapped $pBuffer = DllStructGetPtr($hBuffer) $nBufferLength = DllStructGetSize($hBuffer) $pOverlapped = DllStructGetPtr($hOverlapped) If $bInitial Then $hEvent = DllCall("kernel32.dll", "hwnd", "CreateEvent", "UInt", 0, "Int", True, "Int", False, "UInt", 0) DllStructSetData($hOverlapped, "hEvent", $hEvent[0]) EndIf ;~ http://msdn.microsoft.com/en-us/library/aa365465%28VS.85%29.aspx $aResult = DllCall("kernel32.dll", "Int", "ReadDirectoryChangesW", "hwnd", $hDir, "ptr", $pBuffer, "dword", $nBufferLength, "int", $bSubtree, "dword", BitOR(0x1, 0x2, 0x4, 0x8, 0x10, 0x40, 0x100), "Uint", 0, "Uint", $pOverlapped, "Uint", 0) Return $aResult[0] EndFunc ;==>_SetReadDirectory Func _GetChanges() _MonitorDirectory("ReadDirChanges") EndFunc ;==>_GetChanges Func _GetDirectoryChanges($aDirHandles, $hBuffer, $aOverlapped, $hEvents, $aDirs, $aSubtree, $sFunction) Local $aMsg, $i, $nBytes = 0 $aMsg = DllCall("User32.dll", "dword", "MsgWaitForMultipleObjectsEx", "dword", UBound($aOverlapped), "ptr", DllStructGetPtr($hEvents), "dword", -1, "dword", 0x4FF, "dword", 0x6) $i = $aMsg[0] Switch $i Case 0 To UBound($aDirHandles) - 1 DllCall("Kernel32.dll", "Uint", "ResetEvent", "uint", DllStructGetData($aOverlapped[$i], "hEvent")) _ParseFileMessages($hBuffer, $aDirs[$i], $sFunction) _SetReadDirectory($aDirHandles[$i], $hBuffer, $aOverlapped[$i], False, $aSubtree) Return $nBytes EndSwitch Return 0 EndFunc ;==>_GetDirectoryChanges Func _ParseFileMessages($hBuffer, $sDir, $sFunction) Local $hFileNameInfo, $pBuffer, $FilePath Local $nFileNameInfoOffset = 12, $nOffset = 0, $nNext = 1 $pBuffer = DllStructGetPtr($hBuffer) While $nNext <> 0 $hFileNameInfo = DllStructCreate("dword NextEntryOffset;dword Action;dword FileNameLength", $pBuffer + $nOffset) $hFileName = DllStructCreate("wchar FileName[" & DllStructGetData($hFileNameInfo, "FileNameLength") / 2 & "]", $pBuffer + $nOffset + $nFileNameInfoOffset) Switch DllStructGetData($hFileNameInfo, "Action") Case 0x1 ; $FILE_ACTION_ADDED $Action = "Created" Case 0x2 ; $FILE_ACTION_REMOVED $Action = "Deleted" Case 0x3 ; $FILE_ACTION_MODIFIED $Action = "Modified" Case 0x4 ; $FILE_ACTION_RENAMED_OLD_NAME $Action = "Rename-" Case 0x5 ; $FILE_ACTION_RENAMED_NEW_NAME $Action = "Rename+" Case Else $Action = "Unknown" EndSwitch $FilePath = $sDir & DllStructGetData($hFileName, "FileName") Call($sFunction, $Action, $FilePath) ; Launch the specified function $nNext = DllStructGetData($hFileNameInfo, "NextEntryOffset") $nOffset += $nNext WEnd EndFunc ;==>_ParseFileMessages ;~ ===========================End of FUNCTION _MonitorDirectory() ============================== Edited October 23, 2010 by jackchen Link to comment Share on other sites More sharing options...
stamandster Posted December 22, 2010 Share Posted December 22, 2010 Wow that's a really great function! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now