Posted to tcl by osprey at Fri Jul 02 10:55:19 GMT 2010view raw
- package require Tk
- #---------------
- # http://wiki.tcl.tk/3958
- # atexit - exit hook
- namespace eval AtExit {
- variable atExitScripts [list]
- proc atExit script {
- variable atExitScripts
- lappend atExitScripts \
- [uplevel 1 [list namespace code $script]]
- }
- namespace export atExit
- }
- rename exit AtExit::ExitOrig
- proc exit {{code 0}} {
- variable AtExit::atExitScripts
- set n [llength $atExitScripts]
- while {$n} {
- catch [lindex $atExitScripts [incr n -1]]
- }
- rename exit {}
- rename AtExit::ExitOrig exit
- namespace delete AtExit
- exit $code
- }
- namespace import AtExit::atExit
- #---------------
- # If the <prog>ram successfully starts, its STDOUT and STDERR is dispatched
- # line by line to the <readHandler> (via bgExecGenericHandler) as last arg.
- # <pCount> holds the number of processes called this way. If a <timeout> is
- # specified (as msecs), the process pipeline will be automatically closed after
- # that duration. If specified, and a timeout occurs, <toExit> is called with
- # the PIDs of the processes right before closing the process pipeline.
- # Returns the handle of the process-pipeline.
- #
- # http://wiki.tcl.tk/12704
- proc bgExec {prog readHandler pCount {timeout 0} {toExit ""}} {
- upvar #0 $pCount myCount
- set myCount [expr {[info exists myCount]?[incr myCount]:1}]
- set p [expr {[lindex [lsort -dict [list 8.4.7 [info patchlevel]]] 0] == "8.4.7"?"| $prog 2>@1":"| $prog 2>@stdout"}]
- set pH [open $p r]
- fconfigure $pH -blocking 0; # -buffering line (does it really matter?!)
- set tID [expr {$timeout?[after $timeout [list bgExecTimeout $pH $pCount $toExit]]:{}}]
- fileevent $pH readable [list bgExecGenericHandler $pH $pCount $readHandler $tID]
- atExit [list close $pH]
- return $pH
- }
- proc bgExecGenericHandler {chan pCount readHandler tID} {
- global errorCode
- upvar #0 $pCount myCount
- if {[eof $chan]} {
- after cancel $tID; # empty tID is ignored
- catch {close $chan}; # automatically deregisters the fileevent handler
- # (see Practical Programming in Tcl an Tk, page 229)
- incr myCount -1
- } elseif {[gets $chan line] != -1} {
- # we are not blocked (manpage gets, Practical... page.233)
- lappend readHandler $line
- if {[catch {uplevel $readHandler}]} {
- # user-readHandler ended with error -> terminate the processing
- after cancel $tID
- catch {close $chan}
- incr myCount -1
- }
- }
- }
- proc bgExecTimeout {chan pCount toExit} {
- upvar #0 $pCount myCount
- if {[string length $toExit]} {
- catch {uplevel [list $toExit [pid $chan]]}
- }
- catch {close $chan}
- incr myCount -1
- }
- wm protocol . WM_DELETE_WINDOW {
- if {[tk_messageBox -parent . -title "Close?" -icon question \
- -type yesno -default no -message "Do You want to quit"] == yes} {
- exit
- }
- }
- proc logger {output} {
- puts $logger
- }
- # main
- set h1 [bgExec "notepad.exe" logger pCount]
- # wait for finish
- vwait pCount