ame1011 Posted October 19, 2009 Share Posted October 19, 2009 Hi there, I'm using the following code by zophnog to monitor a folder for file changes: 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 So far everything is going great, I'm recording the operations and the files in a sqlite database which my main program reads on startup to make the required changes that it needs to. My question is: how do I tell which items are folders and which are files? Checking for '.ext' using stringRight or something similar isn't really what I'm looking for as it'll fail if there are dots in the directory names. Also, actually doing a Filesearch for the folder/file isn't feasible because if the operation is a file removal, the file/folder would no longer be there. I tried changing the parameter in the ReadDirectoryChangesW DllCall from: "dword", BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_SIZE,$FILE_NOTIFY_CHANGE_DIR_NAME) to: "dword", $FILE_NOTIFY_CHANGE_DIR_NAME and as expected it began reporting only folder changes. However, I don't know how I would go about recording both file and folder changes while letting me know which are files and which are folders thanks for your help [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font] Link to comment Share on other sites More sharing options...
KaFu Posted October 19, 2009 Share Posted October 19, 2009 If it's a removal, I can't think of a way to determine... otherwise: $filenameANDpath = @WindowsDir if StringInStr(FileGetAttrib($filenameANDpath),"D") then ConsoleWrite($filenameANDpath & " is a directory..." & @crlf) Else ConsoleWrite($filenameANDpath & " is a file..." & @crlf) EndIf $filenameANDpath = "c:\config.sys" if StringInStr(FileGetAttrib($filenameANDpath),"D") then ConsoleWrite($filenameANDpath & " is a directory..." & @crlf) Else ConsoleWrite($filenameANDpath & " is a file..." & @crlf) EndIf  OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
ame1011 Posted October 19, 2009 Author Share Posted October 19, 2009 Exactly what I was thinking... I have a couple solutions but each of them have a least 1 limitation such as the one above, anyone know a method that can do everything? [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font] Link to comment Share on other sites More sharing options...
ame1011 Posted October 23, 2009 Author Share Posted October 23, 2009 Anyone with experience on the subject care to share their input? Like I said above, I'm able to get only folder information specifically or only file information but I'm not sure how to combine the two while being able to differentiate between the two. [font="Impact"] I always thought dogs laid eggs, and I learned something today. [/font] Link to comment Share on other sites More sharing options...
gr8BigGeek Posted January 19, 2010 Share Posted January 19, 2010 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. 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 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 failed to add this file as well sorry mates. Matt MINIMIZE TEST.au3 Link to comment Share on other sites More sharing options...
aguynamedray Posted November 1, 2012 Share Posted November 1, 2012 Any idea on how to pull out the username of the specified domain using the sample code above? 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