argumentum Posted August 15 Share Posted August 15 Out of this help request, I saw that there is $FILE_NOTIFY_CHANGE_SIZE. Now, if the OS knows that it changed, where is the size ? Looking around, starting with Win10/Server2016, there is ReadDirectoryChangesExW with: typedef struct _FILE_NOTIFY_EXTENDED_INFORMATION { DWORD NextEntryOffset; DWORD Action; LARGE_INTEGER CreationTime; LARGE_INTEGER LastModificationTime; LARGE_INTEGER LastChangeTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER AllocatedLength; LARGE_INTEGER FileSize; DWORD FileAttributes; union { DWORD ReparsePointTag; DWORD EaSize; } DUMMYUNIONNAME; LARGE_INTEGER FileId; LARGE_INTEGER ParentFileId; DWORD FileNameLength; WCHAR FileName[1]; } FILE_NOTIFY_EXTENDED_INFORMATION, *PFILE_NOTIFY_EXTENDED_INFORMATION; /* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-file_notify_extended_information */ Saw a couple of examples in C ( this one and this one ) and my request is to have an AutoIt implementation. TIA Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Nine Posted August 15 Share Posted August 15 Based on the example I made you would need to modify/add the following : Global Const $tag_FILE_NOTIFY_EXTENDED_INFORMATION = "dword NextEntryOffset;dword Action;int64 CreationTime;" & _ "int64 LastModificationTime;int64 LastChangeTime;int64 LastAccessTime;int64 AllocatedLength;" & _ "int64 FileSize;dword FileAttributes;dword EaSize;int64 FileId;int64 ParentFileId;dword FileNameLength;" .... While True $tNotify = DllStructCreate($tag_FILE_NOTIFY_EXTENDED_INFORMATION, $pBuffer) $nLength = $tNotify.FileNameLength $tNotify = DllStructCreate($tag_FILE_NOTIFY_EXTENDED_INFORMATION & "wchar FileName[" & $nLength / 2 & "]", $pBuffer) FileNotifyUser($tNotify.Action, $tNotify.FileName, $tNotify.FileSize) .... Local $aRet = DllCall('kernel32.dll', 'bool', 'ReadDirectoryChangesExW', 'handle', $hDirectory, 'struct*', $pBuffer, _ 'dword', $iLength - Mod($iLength, 4), 'bool', $bSubtree, 'dword', $iFilter, 'dword*', 0, 'struct*', $tOverlapped, _ 'ptr', $pCompletion, 'dword', 2) FileNotifyUser should be changed accordingly. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
argumentum Posted August 15 Author Share Posted August 15 (edited) 4 hours ago, Nine said: Based on the example I made you would need to modify/add the following : ..I did but it did not work for me. No clue of what am doing wrong. Please post a running script when you get a chance. Thanks Edit: $FILE_ACTION_RENAMED_NEW_NAME don't trigger Edit2: also, instead of FileNotifyUser($tNotify.Action, $tNotify.FileName, $tNotify.FileSize), could FileNotifyUser($tNotify) work ? Edit3: might as well share what I did: Spoiler expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n ; trying x32 and x64 #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Constants.au3> #include <WinAPI.au3> Opt("MustDeclareVars", True) HotKeySet("{ESC}", Terminate) Global Const $WATCH_PATH = "C:\Apps\Temp" Global Const $BUFFER_LENGTH = 0xFFFF ; 64k ;~ Global Const $NOTIFY_FLAGS = BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME) Global Const $NOTIFY_FLAGS = BitOR($FILE_NOTIFY_CHANGE_FILE_NAME, $FILE_NOTIFY_CHANGE_DIR_NAME, $FILE_NOTIFY_CHANGE_ATTRIBUTES, _ $FILE_NOTIFY_CHANGE_SIZE, $FILE_NOTIFY_CHANGE_LAST_WRITE, $FILE_NOTIFY_CHANGE_LAST_ACCESS, $FILE_NOTIFY_CHANGE_CREATION, $FILE_NOTIFY_CHANGE_SECURITY) Global $tOverlapped, $hDirectory, $hCompletion, $pCompletion, $pDataBuffer, $hEvent Global Const $tag_FILE_NOTIFY_EXTENDED_INFORMATION = "dword NextEntryOffset;dword Action;int64 CreationTime;" & _ "int64 LastModificationTime;int64 LastChangeTime;int64 LastAccessTime;int64 AllocatedLength;" & _ "int64 FileSize;dword FileAttributes;dword EaSize;int64 FileId;int64 ParentFileId;dword FileNameLength;" DirectoryChange() Func DirectoryChange() $tOverlapped = DllStructCreate($tagOVERLAPPED) $hEvent = _WinAPI_CreateEvent(0, False, False) $tOverlapped.hEvent = $hEvent $hDirectory = _WinAPI_CreateFileEx($WATCH_PATH, $OPEN_EXISTING, $FILE_LIST_DIRECTORY, _ BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE, $FILE_SHARE_DELETE), _ BitOR($FILE_FLAG_BACKUP_SEMANTICS, $FILE_FLAG_OVERLAPPED)) $hCompletion = DllCallbackRegister(CompletionRoutineExW, "none", "dword;dword;ptr") $pCompletion = DllCallbackGetPtr($hCompletion) $pDataBuffer = _WinAPI_CreateBuffer($BUFFER_LENGTH) _WinAPI_ReadDirectoryChangesExW($hDirectory, $NOTIFY_FLAGS, $pDataBuffer, $BUFFER_LENGTH, True, $tOverlapped, $pCompletion) OnAutoItExitRegister(CleanUp) While True _WinAPI_WaitForSingleObjectEx($hEvent, 0, 1) Sleep(100) WEnd EndFunc ;==>DirectoryChange ;~ Make decisions on file changes in here Func FileNotifyUserExW($nFileAction, $sFileName, $iFileSize) Switch $nFileAction Case $FILE_ACTION_ADDED ConsoleWrite($iFileSize & " - File added: " & $sFileName & @CRLF) Case $FILE_ACTION_REMOVED ConsoleWrite($iFileSize & " - File removed: " & $sFileName & @CRLF) Case 3 ConsoleWrite($iFileSize & " - File changed something: " & $sFileName & @CRLF) Case $FILE_ACTION_RENAMED_OLD_NAME ConsoleWrite($iFileSize & " - File renamed from: " & $sFileName & @CRLF) Case $FILE_ACTION_RENAMED_NEW_NAME ConsoleWrite($iFileSize & " - File renamed to: " & $sFileName & @CRLF) EndSwitch EndFunc ;==>FileNotifyUserExW Func CleanUp() _WinAPI_CancelIoEx($hDirectory, $tOverlapped) _WinAPI_CloseHandle($hDirectory) _WinAPI_FreeMemory($pDataBuffer) _WinAPI_CloseHandle($hEvent) DllCallbackFree($hCompletion) EndFunc ;==>CleanUp Func CompletionRoutineExW($nError, $nTransfered, $pOverlapped) Local $pBuffer = $pDataBuffer, $tNotify, $nLength While True $tNotify = DllStructCreate($tag_FILE_NOTIFY_EXTENDED_INFORMATION, $pBuffer) $nLength = $tNotify.FileNameLength $tNotify = DllStructCreate($tag_FILE_NOTIFY_EXTENDED_INFORMATION & "wchar FileName[" & $nLength / 2 & "]", $pBuffer) FileNotifyUserExW($tNotify.Action, $tNotify.FileName, $tNotify.FileSize) If Not $tNotify.NextOffset Then ExitLoop $pBuffer += $tNotify.NextOffset WEnd _WinAPI_ReadDirectoryChangesExW($hDirectory, $NOTIFY_FLAGS, $pDataBuffer, $BUFFER_LENGTH, 0, $tOverlapped, $pCompletion) EndFunc ;==>CompletionRoutineExW Func _WinAPI_ReadDirectoryChangesExW($hDirectory, $iFilter, $pBuffer, $iLength, $bSubtree = 0, $tOverlapped = 0, $pCompletion = 0) Local $aRet = DllCall('kernel32.dll', 'bool', 'ReadDirectoryChangesExW', 'handle', $hDirectory, 'struct*', $pBuffer, _ 'dword', $iLength - Mod($iLength, 4), 'bool', $bSubtree, 'dword', $iFilter, 'dword*', 0, 'struct*', $tOverlapped, _ 'ptr', $pCompletion, 'dword', 2) If @error Or Not $aRet[0] Then Return SetError(@error + 10, @extended, 0) Return SetExtended(_WinAPI_GetLastError(), $aRet[0]) EndFunc ;==>_WinAPI_ReadDirectoryChangesExW Func _WinAPI_CancelIoEx($hFile, $tOverlapped) Local $aRet = DllCall('kernel32.dll', 'bool', 'CancelIoEx', 'handle', $hFile, 'struct*', $tOverlapped) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_CancelIoEx Func _WinAPI_WaitForSingleObjectEx($hEvent, $nMilliseconds, $bAlertable = 0) Local $aRet = DllCall('kernel32.dll', 'dword', 'WaitForSingleObjectEx', 'handle', $hEvent, 'dword', $nMilliseconds, 'bool', $bAlertable) If @error Then Return SetError(@error, @extended, 0) Return $aRet[0] EndFunc ;==>_WinAPI_WaitForSingleObjectEx Func Terminate() Exit EndFunc ;==>Terminate Edited August 15 by argumentum more Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
Solution Nine Posted August 15 Solution Share Posted August 15 Definitely buggy on the rename, got same issue as you. I added a Case Else on action and there is no other, so the bug is not about a change in action. Didn't test much the new EX, but size works well. IDK about the other triggers. In any case, this API is not well written. We do not know what has been modified. Won't be using it for sure... Passing $tNofify as a parameter is a good idea. argumentum 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy 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