Page 3 of 4

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

Posted: 02 Feb 2017, 04:33
by r2997790
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

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

Posted: 02 Feb 2017, 05:01
by just me
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%
      }
   }
}

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

Posted: 02 Feb 2017, 05:50
by r2997790
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!

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

Posted: 15 Feb 2017, 17:43
by Guest
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!

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

Posted: 16 Feb 2017, 10:49
by just me
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

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

Posted: 26 Dec 2017, 17:52
by arifsaifee
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....

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

Posted: 28 Dec 2017, 05:35
by elModo7
Excellent! :bravo:

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

Posted: 24 Mar 2018, 16:24
by kczx3
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?

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

Posted: 25 Mar 2018, 03:10
by just me
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.

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

Posted: 30 Mar 2018, 17:02
by JoeWinograd
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

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

Posted: 30 Mar 2018, 17:28
by Flipeador
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.

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

Posted: 30 Mar 2018, 17:31
by kczx3
Joe, did you not look at the fifth parameter that the ReadDirectoryChangesW function accepts? It is pretty clear that bWatchSubtree does just that.

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

Posted: 30 Mar 2018, 18:25
by JoeWinograd
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

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

Posted: 17 Sep 2018, 10:22
by nicrox
Awesome script, thanks

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

Posted: 15 Dec 2018, 18:12
by sinbad
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?

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

Posted: 25 Jun 2019, 06:15
by autocart
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
}

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

Posted: 01 Sep 2019, 16:01
by hasantr
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.

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

Posted: 01 Sep 2019, 16:27
by boiler
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.

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

Posted: 01 Sep 2019, 21:52
by hasantr
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?

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

Posted: 01 Sep 2019, 22:07
by boiler
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.