Skip to content

Latest commit

 

History

History
143 lines (109 loc) · 3.91 KB

sample_117.md

File metadata and controls

143 lines (109 loc) · 3.91 KB

Home

Monitoring changes in a directory

Note that this document contains some links to the old news2news website which does not work at the moment. This material will be available sometime in the future.

Before you begin:

Imagine that an application needs to be notified upon file changes in a particular directory: files added or deleted, changed, or accessed. The ChangeNotification function is an answer.

After starting this code sample, try to add, change or delete files in the target directory (must be valid path). Create a FoxPro table in it and operate with its records.

See also::


Code:

PUBLIC oForm
oForm = CREATEOBJECT("Tform", SYS(2023)) && watching TEMP dir
oForm.Visible = .T.
* end of main

DEFINE CLASS Tform As Form
#DEFINE FILE_NOTIFY_CHANGE_FILE_NAME 1
#DEFINE FILE_NOTIFY_CHANGE_DIR_NAME 2
#DEFINE FILE_NOTIFY_CHANGE_ATTRIBUTES 4
#DEFINE FILE_NOTIFY_CHANGE_SIZE 8
#DEFINE FILE_NOTIFY_CHANGE_LAST_WRITE 16
#DEFINE FILE_NOTIFY_CHANGE_LAST_ACCESS 32
#DEFINE FILE_NOTIFY_CHANGE_CREATION 64
#DEFINE FILE_NOTIFY_CHANGE_SECURITY 128
#DEFINE INVALID_HANDLE_VALUE -1
#DEFINE WAIT_OBJECT_0 0
#DEFINE WATCHING_INTERVAL 1000  && milliseconds

PROTECTED hNotify, PathBeingWatched

	Width=400
	Height=150
	MaxButton=.F.
	BorderStyle=2
	AutoCenter=.T.
	Caption="Watching directory"

	hNotify=INVALID_HANDLE_VALUE
	PathBeingWatched=""
	
	ADD OBJECT lblTarget As Label WITH Left=10, Top=7, Autosize=.T.
	ADD OBJECT tm As Timer WITH Interval=0

	ADD OBJECT lblAlert As Label WITH Left=10, Top=30,;
	Autosize=.T., Caption="Notification:"

FUNCTION Init(cPath)
	THIS.declare
	THIS.PathBeingWatched = FULLPATH(m.cPath)

	IF Not THIS.StartWatching()
		= MESSAGEBOX("Notification handle error.")
		RETURN .F.
	ENDIF

PROCEDURE Destroy
	THIS.StopWatching

PROTECTED FUNCTION StartWatching
	LOCAL lResult

	* no subdirs watched
	THIS.hNotify = FindFirstChangeNotification(;
		THIS.PathBeingWatched, 0,;
		FILE_NOTIFY_CHANGE_FILE_NAME +;
		FILE_NOTIFY_CHANGE_LAST_WRITE )

	lResult = (THIS.hNotify <> INVALID_HANDLE_VALUE)

	IF lResult
		THIS.lblTarget.Caption = "Watched: " +;
			THIS.PathBeingWatched
		THIS.tm.Interval = WATCHING_INTERVAL
	ENDIF
RETURN  lResult

PROTECTED PROCEDURE ContinueWatching
	IF FindNextChangeNotification(THIS.hNotify) = 0
		THIS.StopWatching
		= MESSAGEBOX("Request error.")
		THIS.Release
	ENDIF
	THIS.tm.Interval = WATCHING_INTERVAL

PROTECTED FUNCTION StopWatching
	THIS.tm.Interval = 0
	IF THIS.hNotify <> INVALID_HANDLE_VALUE
		= FindCloseChangeNotification(THIS.hNotify)
	ENDIF

FUNCTION _signaled		&& returns signaled state
RETURN (WaitForSingleObject(THIS.hNotify, 0) = WAIT_OBJECT_0)

PROCEDURE _notify		&& triggered on event
	LOCAL cMessage
	cMessage = "Notification: " + TTOC(DATETIME())
	THIS.lblAlert.Caption = cMessage
	ACTIVATE SCREEN
	? cMessage
	THIS.ContinueWatching

PROCEDURE tm.Timer
	IF ThisForm._signaled()
		ThisForm._notify
	ENDIF

PROTECTED PROCEDURE declare
	DECLARE SHORT FindNextChangeNotification IN kernel32;
		INTEGER hChangeHandle

	DECLARE SHORT FindCloseChangeNotification IN kernel32;
		INTEGER hChangeHandle

	DECLARE INTEGER FindFirstChangeNotification IN kernel32;
		STRING lpPathName, INTEGER bWatchSubtree,;
		INTEGER dwNotifyFilter

	DECLARE INTEGER WaitForSingleObject IN kernel32;
		INTEGER hHandle, INTEGER dwMilliseconds

ENDDEFINE  

Listed functions:

FindCloseChangeNotification
FindFirstChangeNotification
FindNextChangeNotification
WaitForSingleObject