#cs ---------------------------------------------------------------------------- AutoIt Version: 3.2.10.0 Author: zorphnog (M. Mims) Script Function: Monitors the user defined directories for file activity. #ce ---------------------------------------------------------------------------- #include #include #include #include #include #include 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,$FILE_NOTIFY_CHANGE_SECURITY), _ "uint", 0, _ "uint", $pOverlapped, _ "uint", 0) If $aResult[0] = 0 Then ConsoleWrite("!> ReadDirectoryChangesW Error(" & @error & "): " & _WinAPI_GetLastErrorMessage() & @LF) Exit EndIf Return $aResult[0] EndFunc