ffcn: Implementation of the Win32-API-Call FindFirstChangeNotification()Notes:
################################################################################
# Modul: ffcn.tcl
# Stand: 11.03.2004
# Zweck: Mapping von Win32-API-Calls: 'FindFirstChangeNotification'
# 'FindCloseChangeNotification'
# 'WaitForSingleObject'
# Autor: (C) M.Hoffmann, März 2004
# Siehe:
# API-Deklaration (Original Win32):
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/findfirstchangenotification.asp
# FFIDL:
# http://wiki.tcl.tk/1197, http://www.elf.org/ffidl/
# API-Deklarationen in PB:
# DECLARE FUNCTION FindFirstChangeNotification LIB "KERNEL32.DLL" ALIAS
# "FindFirstChangeNotificationA" (lpPathName AS ASCIIZ,
# BYVAL bWatchSubtree AS LONG,
# BYVAL dwNotifyFilter AS DWORD) AS DWORD
# DECLARE FUNCTION FindCloseChangeNotification LIB "KERNEL32.DLL" ALIAS
# "FindCloseChangeNotification" (BYVAL hChangeHandle AS DWORD) AS LONG
# DECLARE FUNCTION WaitForSingleObject LIB "KERNEL32.DLL" ALIAS
# "WaitForSingleObject" (BYVAL hHandle AS DWORD,
# BYVAL dwMilliseconds AS DWORD) AS DWORD
# FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001 default
# FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002 default
# FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004 default
# FILE_NOTIFY_CHANGE_SIZE = 0x00000008 default
# FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010 default
# FILE_NOTIFY_CHANGE_LAST_ACCESS= 0x00000020
# FILE_NOTIFY_CHANGE_CREATION = 0x00000040 default
# FILE_NOTIFY_CHANGE_SECURITY = 0x00000100
# INVALID_HANDLE_VALUE = 0xffffffff
# INFINITE = 0xffffffff
# Datentypen:
# http://www.a-m-i.de/tips/strings/strings.php
# URL homepages.fh-giessen.de/~hg6661/vorlesungen/systemschnittstellen no longer avail
# script/win/datentypen.php
# Offen: Namespace,RoboDOCu,Konstanten implementieren,Catch für ffidl::callout,
# Abbruchmöglichkeit,nicht blockierende Variante,gleich die tatsächlichen
# Änderungen zurückliefern (glob vorher/nachher;intersect liefern)
################################################################################
package provide ffcn 1.0
package require Ffidl 0.5
ffidl::callout dll_ffcn {pointer-utf8 long long} long \
[ffidl::symbol kernel32.dll FindFirstChangeNotificationA]
ffidl::callout dll_fccn {long} long \
[ffidl::symbol kernel32.dll FindCloseChangeNotification]
ffidl::callout dll_wfso {long long} long \
[ffidl::symbol kernel32.dll WaitForSingleObject]
# Dieser Call wartet (wohl blockierend), bis eine Änderung im Verzeichnis auftritt
proc waitChange {pathName {includeSubDirs 0} {notifyFilter 0x5F}} {
# Überwachung einleiten
if {[catch {dll_ffcn $pathName $includeSubDirs $notifyFilter} h] ||
$h == -1} {
return -code error "FindFirstChangeNotification() gescheitert ($h)"
}
# puts $h
# Achtung: das folgende blockiert vermutlich Tcl-Eventloop!
# Überwachung starten (momentan OHNE CATCH)
set r [dll_wfso $h 0xffffffff]
# Überwachung beenden (momentan OHNE CATCH)
set r [dll_fccn $h]
return {}
}
################################################################################
Example:
package require ffcn
# because of the Win32-API-Call waitForSingleObject(), the following call blocks
# the whole program; I haven't found a solution for this yet...
# If a file in e:/demodir is created, deleted etc., the call returns:
#
waitChange e:/demodir
A 'tcl-only' alternative for tracking directory-changes using a polling-method (so the after
ms-Value should not be too small because of cpu-load-aspects!):
proc watchDirChange {dir intv {script {}} {lastMTime {}}} {
set nowMTime [file mtime $dir]
if [string eq $lastMTime ""] {
set lastMTime $nowMTime
} elseif {$nowMTime != $lastMTime} {
# synchronous execution, so no other after event may fire in between
catch {uplevel #0 $script}
set lastMTime $nowMTime
}
after $intv [list watchDirChange $dir $intv $script $lastMTime]
}
watchDirChange e:/work 5000 {
puts stdout {Directory 'e:/work' changed!}
}
vwait forever
- Another (yet undocumented) alternative, using winutils, is mentioned here: http://wiki.tcl.tk/2631.
- And another one using WMI (waiting to be adapted to tcom) is here: http://www.microsoft.com/resources/documentation/windows/2000/server/scriptguide/en-us/sas_fil_overview.mspx!
- And with version 0.6 of twapi [1], there seems to be there, what I've been missing until now....: twapi::begin|cancel_filesystem_monitor, which works simple with callback-procs! But, in contrast of available "high-level" (laugh!) Microsoft-calls, it's again up to the programmer to determine what the actual changes in the filesystem really are... To see how that task can be done in principle, see Matthias Hoffmann - Other Utilities - Dirwatcher.
- APN As of 0.7, the TWAPI callbacks do contain some information like what file/dir changed, and the operation (write, rename, delete etc.)
- Also, CL thinks SO said GPS is working in this area.