Updated 2013-07-17 16:48:32 by traff

There are multiple efforts and products offering expect for MS Windows.

Gordon Chaffee ported Expect 5.21r1b1 . Binary and source are available at [1], and also present in MyrmecoX (?). This corresponds to Tcl version 8.0.

An up-to-date port of Expect (based off 5.43) is available from ActiveState [2], included in ActiveTcl 8.4.11.1 or later. It works with Tcl 8.4 and is fully stubs-enabled, allowing it to be wrapped with TclApp (part of the Tcl Dev Kit) to create single-file deployable executables. This is similar to the Chaffee port in that it doesn't have interact, fork or overlay, but the bulk of the automation core is available.

It could get interact if someone really needs it. All that's needed is lots of development time and good verification test cases. -- DG

cygwin's Expect works fine under Cygwin as long as what you're expect'ing upon is a cygwin application. It does not work with normal/native Win32 console applications. -- Andreas Kupries [2001-sep-20]

During the early winter 2001-2002, Telindustrie LLC briefly supported David Gravereaux's work to port 8.4 to Windows. Davy's pretty much the world's most knowledgeable person about what this will involve. He writes,
 "There is a *somewhat* working 8.4 ready binary of Expect for windows @
   http://sf.net/project/showfiles.php?group_id=13179 . It's far from
   done. Using spawn with the -open option one can 'expect' on an already
   open channel, such as a socket or a serial port. The 'slave driver'
   aspect of spawn is where all the deep black magic is.
   The mojo isn't yet complete."

The windows specific code is already in the official repository off on a branch [3]

There are lots of ways this could go. Perl (and Python?) people might help out with Expect, and Win* expertise perhaps would be part of the package. Also interesting is a comp.lang.tcl exchange [4] between Jiang Wu and Jeffrey Hobbs; note mention of how more of Expect might move into the Tcl core.

[Why and how it doesn't work for Win95. Problems with interact.] [Experience with Win2000.] [ Pure-Tcl telnet available--this sometimes suffices.]

[Expect 5.25/Tcl 7.6 for Japanese.] [5.31/8.2 as source.]

[ Tony Summerfelt's been mostly successful with Expect under Win2000.]

Is there a need for a trap to receive the "signal" when Expect is used as a Windows service? [5]

IMO, No. The windows model provides this and the "shell" being used for the service control should get "going down" notices and hopefully "do the right thing". If expect.exe knows nothing for being a windows service, for which it shouldn't being a CLI shell, one should build a shell with all the needed service parts to get the notifications they need. See tclsvc - Tcl as an NT Service -- DG

Many people who think they need Expect do not need Expect, for Windows in particular.

LV Sometimes people talk about wanting Expect running under Windows, but it turns out that they really are wanting to drive GUI applications, which is a use for which Expect is not intended.

escargo 19 Apr 2005 - Using driving as a search produced (among others): Techniques for 'driving' Windows applications.

AM Expect for Windows as available in ActiveTcl 8.4.xx works very very nicely, but there is a caveat:
   Do not use a DOS-box and tclsh to run your expect scripts.

I have no idea why, but I really had trouble getting a simple expect script to run (exp_send did not work if you gave it an explicitly spawn ID, the whole program hung when the input from the spawned process was not a complete line - the very reason I needed Expect in the first place).

These problems are probably due to the way DOS-boxes work. It all works fine when you use wish.

LV What is a DOS-box?

DG: I think what AM is saying refers to executing commands from the system prompt. IOW:
 spawn cmd.exe
 exp_send "ftp.exe\r"
 expect ">"
 exp_send "open ftp.example.com\r"
 ...

cmd.exe is not needed! Just spawn ftp.exe. I think there's a bug with how E4W tries to get text through cmd.exe but can't for some reason (unknown).

SG: cmd.exe is not needed if you're spawning an .exe file - it is necessary if you're trying to spawn a .bat file. AIUI, there's no way to use ActiveState's expect with a bat file. The version of expect with cygwin seems to work with cmd.exe, however.

Njay: I had worked with expect for Windows before, but I recently was unable to get it working on a quad-core with XP. spawn simply doesn't launch the process and doesn't issue any error. Also tried the "open |" feature but there were some unexplainable quirks so, I started to think that a simple version of expect could be implemented in Tcl. So here it is; the limitations are plenty but for basic applications it should do the trick.
 set ::timeout 10

 proc spawn {args} {
     global gExpPipe
     set gExpPipe [open |[join $args " "] r+]
     fconfigure $gExpPipe -blocking 0 -buffering none -translation binary
     fileevent $gExpPipe readable [list expMyRead $gExpPipe]
 }

 proc expMyRead {chn} {
     if {[eof $chn]} {
         set ::gNewChar EOF
         catch {close $chn}
     } else {
         set ::gNewChar [read $chn 1]
     }
 }

 proc exp_continue {} {
     set ::gExpStop 0
 }

 proc expect {arg} {
    global gNewChar gExpStop timeout

    set llenArg [llength $arg]

    set gExpStop 0

    while {!$gExpStop} {
        if {$timeout >= 0} {
            set timerId [after [expr {$timeout * 1000}] {set gNewChar TIMEOUT}]
        }

        catch {unset gNewChar}
        vwait ::gNewChar
        # puts -nonewline " |GOT $::gNewChar| "

        catch {after cancel $timerId}

        switch $gNewChar {
            \r {
                continue
            }
            TIMEOUT {
                # Look for a timeout rule and execute if exists, otherwise issue an error
                set i [lsearch -exact $arg timeout]
                if {$i >= 0} {
                    set script [lindex $arg [expr {$i + 1}]]
                    uplevel [list eval $script]
                    return
                }
                error "Timeout on expect $arg"
            }
            EOF {
                error "The process being controlled just died"
            }
        }

        puts -nonewline $gNewChar
        flush stdout

        append buffer $gNewChar

        set gExpStop 0

        # Look for a matching rule
        for {set idx 0} {$idx < $llenArg} {incr idx} {
            set token [lindex $arg $idx]
            if {$token == "-re"} {   ;# Tcl8.3 does not support "eq"
                set re [lindex $arg [incr idx]]
                set re [uplevel [list subst -nocommands $re]]
                set script [lindex $arg [incr idx]]
                if {[regexp -nocase -- $re $buffer 0 1 2 3 4 5 6 7 8 9]}  {
                    set gExpStop 1
                    for {set eoi 0} {$eoi < 10} {incr eoi} {
                        set script [string map [list \$expect_out($eoi,string) \{[set $eoi]\}] $script]
                    }
                    uplevel [list eval $script]
                    set buffer ""
                }
            } else {
                set patt [uplevel [list subst -nocommands $token]]
                set script [lindex $arg [incr idx]]
                if {[string match *$patt* $buffer]} {
                    set gExpStop 1
                    uplevel [list eval $script]
                    set buffer ""
                    set idx $llenArg
                }
            }
        }
    }
 }

 proc send_user {args} {
     eval uplevel \{puts $args\}
 }

 proc send {arg} {
     puts -nonewline $arg;              flush stdout
     puts -nonewline $::gExpPipe $arg;  flush $::gExpPipe
 }

 proc pause {time} {
     after $time {set ::___done_pause 1}
     vwait ::___done_pause
 }

Njay: I did a minor update on the expect proc above and added the pause proc. This code is a lib.

AMG: What does [send_user] do? Can't it just be "puts $args"?

send_user takes care that the arguments are evaluated in the caller's context. It is written as if the default context could have variables that would hide the caller's variables. Of course the client could have had that outcome by just using puts. send_user is "expected" to be in expect though.

RJ: There's currently no version of Expect that works correctly with 64bit Windows 7 and above. Does anyone have time to get this working?

[aqui] - 2013-01-06 10:05:51

As I have investigated, "Expect" does NOT appear to be included in ActiveTCL v8.5 for windows (Installer name: ActiveTCL8.5.13.0.296436-win32-ix86-threded.exe). Could anyone please confirm that and/or update the relevant text.

[traff] - 2013-07-17 16:48:32

Hi, the link to Gordon Chaffee's Expect port in invalid(maybe outdated). Do you know what could be the right link now?