WatchFolder() - updated on 2021-10-14

Post your working scripts, libraries and tools for AHK v1.1 and older
r2997790
Posts: 71
Joined: 02 Feb 2017, 02:46

Re: WatchFolder() - updated on 2016-11-30

02 Feb 2017, 04:33

just me wrote:
WatchFolder wrote:Disadvantages (objective):
  • No filter options.
So you have to check the file extensions within the UserFunction.
Thanks justme.

Code: Select all

; WatchFolder - Reportfunctions
ReportFunction(Directory, Changes) { 
 For Each, Change In Changes {
       Action := Change.Action
       Name := Change.Name
	   ; -------------------------------------------------------------------------------------------------------------------------
       ; Action 1 (added) = File gets added in the watched folder
	   If (Action = 1)
	   	 msgbox hello world
       }
}
Could you give an example, based on your first post, of how to do this in the user script? I'd be very grateful.

I presume it goes in here as a nested loop (I'm a newbie, so sorry for the questions):

Code: Select all

       
       ; Action 1 (added) = File gets added in the watched folder
	   If (Action = 1)
	   	>>>
	   	 msgbox hello world
       }
>>> would this be another If (???? = "*.mobi, *.ebub")?

I am not sure what the new file that is found is defined as and how to interogate it. Could you offer some wisdom? I am sure it will help a number of us.

Danka,
R
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: WatchFolder() - updated on 2016-11-30

02 Feb 2017, 05:01

Maybe something like this (not tested):

Code: Select all

; WatchFolder - Reportfunction
ReportFunction(Directory, Changes) {
   Static MyExtensions := "mobi,epub"
   For Each, Change In Changes {
      Action := Change.Action
      Name := Change.Name
      SplitPath, Name, , , Extension
      If Extension Not In MyExtensions ; skip files depending on the extension
         Continue
      ; -------------------------------------------------------------------------------------------------------------------------
      ; Action 1 (added) = File gets added in the watched folder
      If (Action = 1)
         MsgBox, %Name%
      }
   }
}
r2997790
Posts: 71
Joined: 02 Feb 2017, 02:46

Re: WatchFolder() - updated on 2016-11-30

02 Feb 2017, 05:50

Fantastic, thank you!

I was able to do this:

Code: Select all

 SplitPath, Name, , , Extension
       If (Extension  = "epub")
        	msgbox do this to an epub
       If (Extension  = "mobi")
        	msgbox do that to a mobi
        Continue


I really appreciate the feedback!
Guest

Re: WatchFolder() - updated on 2016-11-30

15 Feb 2017, 17:43

Hey there,

Sorry if this is a noob question. I am relatively new to AHK and scripting in general.

I am trying to watch a folder for any .xml files that get added, renamed, or modified in it. I then save them as .html and open them in a web browser.
This is working whenever a new file gets added, or is renamed within the folder, but it is not triggering in case the file's timestamp is changed (i.e. opening the .xml, changing some text and saving it).

I assumed that this line would mean that if a file's timestamp is modified, it would trigger the action, but I can't seem to get it to work.

Code: Select all

FILE_ACTION_MODIFIED           = 3   (0x00000003) : The file was modified.
Here is my code:

Code: Select all

#Persistent
WatchFolder("C:\Users\noob\Desktop\exported_XMLs", "ReportFunction")


; WatchFolder - Reportfunctions
ReportFunction(Directory, Changes)
{
	For Each, Change In Changes 
	{
		Action := Change.Action
		Name := Change.Name
		; -------------------------------------------------------------------------------------------------------------------------
		; Action 1 (added) = File gets added in the watched folder
		
		If (Action = 1 or Action = 3 or Action = 4)
		{
			FullPath = %Name%
			StylesFile := "C:\Users\noob\Desktop\exported_XMLs\Preview\HTML_Style.txt"
			
			SplitPath, FullPath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
			If (OutExtension = "xml")
			{
				FileCopy, %FullPath%, %OutDir%\Preview\%OutNameNoExt%.html, 1
			
				FileRead, styleContents, %StylesFile%
				FileAppend, %styleContents%, %OutDir%\Preview\%OutNameNoExt%.html
			
				MsgBox, 4, Preview File?, You have just exported "%Name%". Would you like to preview it in Google Chrome?, 60
			
					IfMsgBox, Yes
					Run, C:\Program Files (x86)\Google\Chrome\Application\chrome.exe "%OutDir%\Preview\%OutNameNoExt%.html"
			}
		}
	}
	return
}
Can someone tell me how I could have this work so it would also trigger in case the file gets modified while already in the folder?

Thank you!
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: WatchFolder() - updated on 2016-11-30

16 Feb 2017, 10:49

Look at the parameter list of WatchFolder(). You have to set Watch to an appropriate value to report changes other than default:
WatchFolder.ahk wrote:

Code: Select all

;     Watch       -  The kind of changes to watch for. This can be one or any combination of the FILE_NOTIFY_CHANGES_...
;                    values specified below.
;                    Default: 0x03 - FILE_NOTIFY_CHANGE_FILE_NAME + FILE_NOTIFY_CHANGE_DIR_NAME
arifsaifee

Re: WatchFolder() - updated on 2016-11-30

26 Dec 2017, 17:52

This lib has a bug. It cannot tell you if a file was updated, possibly because the watch flags (FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME) overlap with (FILE_ACTION_MODIFIED). Or maybe I am missing something here....
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: WatchFolder() - updated on 2016-11-30

24 Mar 2018, 16:24

Is the ReadDirectoryChangesW function the best way to watch a single file for changes? I went to the File Management section of that MSDN collection of pages and didn't see anything for simply watching a file.

Would the userFunc simply have to filter things out by filename from the events?
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: WatchFolder() - updated on 2016-11-30

25 Mar 2018, 03:10

kczx3 wrote:Is the ReadDirectoryChangesW function the best way to watch a single file for changes?
I don't know.
Would the userFunc simply have to filter things out by filename from the events?
Yes.
User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: WatchFolder() - updated on 2016-11-30

30 Mar 2018, 17:02

Hi just me,

First, a big "Thank You!" for this excellent addition to the AutoHotkey community.

I was just reading the doc at the MSDN link in your script:
ReadDirectoryChangesW function

In the "Meaning" entry of all eight "Value" entries, it says, "...in the watched directory or subtree..." So, that seems to imply that all calls to the ReadDirectoryChangesW function will include subtrees. But your WatchFolder function has a True/False parameter for Subtree, which implies that it is possible to control the inclusion/exclusion of subtrees when calling ReadDirectoryChangesW. I'm hoping that you can explain this seeming discrepancy. Thanks much, Joe
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: WatchFolder() - updated on 2016-11-30

30 Mar 2018, 17:28

JoeWinograd wrote:In the "Meaning" entry of all eight "Value" entries, it says [...]
I think you've overlooked the bWatchSubtree parameter.
ReadDirectoryChangesW wrote:If this parameter is TRUE, the function monitors the directory tree rooted at the specified directory. If this parameter is FALSE, the function monitors only the directory specified by the hDirectory parameter.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: WatchFolder() - updated on 2016-11-30

30 Mar 2018, 17:31

Joe, did you not look at the fifth parameter that the ReadDirectoryChangesW function accepts? It is pretty clear that bWatchSubtree does just that.
User avatar
JoeWinograd
Posts: 2177
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: WatchFolder() - updated on 2016-11-30

30 Mar 2018, 18:25

Thanks, folks, my bad...I was focused on the write-ups in the table and didn't read about the params. It is definitely clear (copied here under "Fair Use"):
bWatchSubtree [in]
If this parameter is TRUE, the function monitors the directory tree rooted at the specified directory. If this parameter is FALSE, the function monitors only the directory specified by the hDirectory parameter.
Regards, Joe
nicrox
Posts: 14
Joined: 14 Mar 2016, 19:05

Re: WatchFolder() - updated on 2016-11-30

17 Sep 2018, 10:22

Awesome script, thanks
sinbad
Posts: 40
Joined: 01 Mar 2018, 09:32

Re: WatchFolder() - updated on 2016-11-30

15 Dec 2018, 18:12

Hi this is great but I've found a slight problem. Mine does not always detect a change if I coy a file across the network. Has anyone else experienced this?
autocart
Posts: 214
Joined: 12 May 2014, 07:42

Re: WatchFolder() - updated on 2016-11-30

25 Jun 2019, 06:15

THANK YOU, just me!
If I may make a suggestion for the sample file, I would disable the checkboxes while it is running, so it is clear that un/checking them makes no difference unless restarted, because then they can't be un/checked while it is running.

BTW, is there a specific reason to why SetBatchLines is set to -1?

Code: Select all

#NoEnv
#Warn
#Include WatchFolder.ahk
SetBatchLines, -1
; ----------------------------------------------------------------------------------------------------------------------------------
Gui, Margin, 20, 20
Gui, Add, Text, , Watch Folder:
Gui, Add, Edit, xm y+3 w730 vWatchedFolder cGray +ReadOnly, Select a folder ...
Gui, Add, Button, x+m yp w50 hp +Default vSelect gSelectFolder, ...
Gui, Add, Text, xm y+5, Watch Changes:
Gui, Add, Checkbox, xm y+3 vSubTree, In Sub-Tree
Gui, Add, Checkbox, x+5 yp vFiles Checked, Files
Gui, Add, Checkbox, x+5 yp vFolders Checked, Folders
Gui, Add, Checkbox, x+5 yp vAttr, Attributes
Gui, Add, Checkbox, x+5 yp vSize, Size
Gui, Add, Checkbox, x+5 yp vWrite, Last Write
Gui, Add, Checkbox, x+5 yp vAccess, Last Access
Gui, Add, Checkbox, x+5 yp vCreation, Creation
Gui, Add, Checkbox, x+5 yp vSecurity, Security
Gui, Add, ListView, xm w800 r15 vLV, TickCount|Folder|Action|Name|IsDir|OldName|%A_Space%
Gui, Add, Button, xm w100 gStartStop vAction +Disabled, Start
Gui, Add, Button, x+m yp wp gPauseResume vPause +Disabled, Pause
Gui, Add, Button, x+m yp wp gCLear, Clear
Gui, Show, , Watch Folder
GuiControl, Focus, Select
Return
; ----------------------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------------------
Clear:
   LV_Delete()
Return
; ----------------------------------------------------------------------------------------------------------------------------------
PauseResume:
   GuiControlGet, Caption, , Pause
   If (Caption = "Pause") {
      WatchFolder("**PAUSE", True)
      GuiControl, Disable, Action
      GuiControl, , Pause, Resume
   }
   ELse {
      WatchFolder("**PAUSE", False)
      GuiControl, Enable, Action
      GuiControl, , Pause, Pause
   }
Return
; ----------------------------------------------------------------------------------------------------------------------------------
StartStop:
   Gui, +OwnDialogs
   Gui, Submit, NoHide
   If !InStr(FileExist(WatchedFolder), "D") {
      MsgBox, 0, Error, "%WatchedFolder%" isn't a valid folder name!
      Return
   }
   GuiControlGet, Caption, , Action
   If (Caption = "Start") {
      Watch := 0
      Watch |= Files ? 1 : 0
      Watch |= Folders ? 2 : 0
      Watch |= Attr ? 4 : 0
      Watch |= Size ? 8 : 0
      Watch |= Write ? 16 : 0
      Watch |= Access ? 32 : 0
      Watch |= Creation ? 64 : 0
      Watch |= Security ? 256 : 0
      If (Watch = 0) {
         GuiControl, , Files, 1
         GuiControl, , Folders, 1
         Watch := 3
      }
      If !WatchFolder(WatchedFolder, "MyUserFunc", SubTree, Watch) {
         MsgBox, 0, Error, Call of WatchFolder() failed!
         Return
      }
      GuiControl, , Action, Stop
      GuiControl, Disable, Select
      GuiControl, Enable, Pause
			GuiControl, Disable, SubTree
			GuiControl, Disable, Files
			GuiControl, Disable, Folders
			GuiControl, Disable, Attr
			GuiControl, Disable, Size
			GuiControl, Disable, Write
			GuiControl, Disable, Access
			GuiControl, Disable, Creation
			GuiControl, Disable, Security
   }
   Else {
      WatchFolder(WatchedFolder, "**DEL")
      GuiControl, , Action, Start
      GuiControl, Enable, Select
      GuiControl, Disable, Pause
			GuiControl, Enable, SubTree
			GuiControl, Enable, Files
			GuiControl, Enable, Folders
			GuiControl, Enable, Attr
			GuiControl, Enable, Size
			GuiControl, Enable, Write
			GuiControl, Enable, Access
			GuiControl, Enable, Creation
			GuiControl, Enable, Security
   }
Return
; ----------------------------------------------------------------------------------------------------------------------------------
SelectFolder:
   FileSelectFolder, WatchedFolder
   If !(ErrorLevel) {
      GuiControl, +cDefault, WatchedFolder
      GuiControl, , WatchedFolder, %WatchedFolder%
      GuiControl, Enable, Action
   }
Return
; ----------------------------------------------------------------------------------------------------------------------------------
MyUserFunc(Folder, Changes) {
   Static Actions := ["1 (added)", "2 (removed)", "3 (modified)", "4 (renamed)"]
   TickCount := A_TickCount
   GuiControl, -ReDraw, LV
   For Each, Change In Changes
      LV_Modify(LV_Add("", TickCount, Folder, Actions[Change.Action], Change.Name, Change.IsDir, Change.OldName, ""), "Vis")
   Loop, % LV_GetCount("Columns")
      LV_ModifyCol(A_Index, "AutoHdr")
   GuiControl, +Redraw, LV
}
hasantr
Posts: 933
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: WatchFolder() - updated on 2016-11-30

01 Sep 2019, 16:01

d = , WatchFolder("D:\", "ReportFunction",3,113)
WatchFolder("C:\", "ReportFunction",3,113) . d

Can we track multiple paths using a variable? It doesn't work like above.
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: WatchFolder() - updated on 2016-11-30

01 Sep 2019, 16:27

You can track multiple paths by using a different UserFunction for each. You could have each of your separate user functions pass their results to your common ReportFunction if that's what you're looking to accomplish.
hasantr
Posts: 933
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: WatchFolder() - updated on 2016-11-30

01 Sep 2019, 21:52

boiler wrote:
01 Sep 2019, 16:27
You can track multiple paths by using a different UserFunction for each. You could have each of your separate user functions pass their results to your common ReportFunction if that's what you're looking to accomplish.
I don't know how many folders I'm watching. Maybe two, maybe five. I can build a long list like this through a loop.
d =, WatchFolder ("D: \", "ReportFunction", WatchFolder ("D: \", "ReportFunction", WatchFolder ("D: \", "ReportFunction",
3,113 ) WatchFolder ("C: \", "ReportFunction", 3,113) . d

any solution?
User avatar
boiler
Posts: 16767
Joined: 21 Dec 2014, 02:44

Re: WatchFolder() - updated on 2016-11-30

01 Sep 2019, 22:07

You can build the list with a loop using the same UserFunc for all of them. The return parameters will identify what changed and how, so you can sort out the feedback in your user function. I’m not seeing what you are trying to get out of it with your “d” variable in your example.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: gwarble and 113 guests