I see -ashell- on SSC but that only lets me access the log of stdout after the shell closes. Why is it displayed in Linux (and, I believe, Mac) but not Windows?
-
Login or Register
- Log in with
windowsmonitor, command(ping 127.0.0.1 -n 20)
/* When Stata calls another application in Windows, it can't access the stdout/stderr streams until the 'command prompt' window closes, unlike Linux and (I believe) OS X. The way around this is to call your other application with winexec not shell (or !), then get it to write output to a file, like the one called "delete-me.txt" in this program. You need to define a particular line that indicates it's finished, otherwise Stata won't know to stop looking. Here I just have Stata read the file every 2 seconds and look for new content to display until that content is "Finished!" It assumes your other application is only ever adding lines on the end of the text file. Example: windowsmonitor, command(ping 127.0.0.1 -n 20) */ capture program drop windowsmonitor program define windowsmonitor syntax ,COMMAND(string asis) [ WINLOGfile(string asis) waitsecs(integer 10) ] // default winlogfile if ("`winlogfile'"=="") { local winlogfile "delete-me.txt" } // delete any existing winlogfile ! del `winlogfile' // construct batch file file open sb using "windowsmonitor.bat", write text replace file write sb "`macval(command)'" _n file write sb "echo Finished!" _n file close sb // issue command, piping output to winlogfile winexec "windowsmonitor.bat" > `winlogfile' // wait up to waitsecs seconds for winlogfile to appear local loopcount=0 capture confirm file `winlogfile' while _rc & (`loopcount'<`waitsecs') { sleep 1000 capture confirm file `winlogfile' local ++loopcount } // start reading from winlogfile capture file close sout file open sout using `winlogfile', read text local linecount=0 while("`macval(lastline)'"!="Finished!") { sleep 2000 // display everything after the linecount-th line file seek sout 0 file read sout line local newlinecount=1 if `newlinecount'>`linecount' { dis as result "`macval(line)'" } while r(eof)==0 { file read sout line if r(eof)==0 { local ++newlinecount if `newlinecount'>`linecount' { dis as result "`macval(line)'" } local lastline="`macval(line)'" } } local linecount=`newlinecount' } capture file close sout ! del `winlogfile' end
program define win_stream mata win_stream(`"`0'"') end mata: void win_stream(string scalar cmd) { tf = st_tempfilename() stata(sprintf("shell echo --begin-- > %s", tf)) tf_bat = st_tempfilename() + ".bat" fh_cmd = fopen(tf_bat, "rw") fput(fh_cmd, sprintf("%s\necho --end--", cmd)) fclose(fh_cmd) stata(sprintf("winexec %s >> %s 2>&1", tf_bat, tf)) pos = 0 thisl = "" while (thisl != "--end--") { fh = fopen(tf, "r") // "r": read-only fseek(fh, pos, -1) // go to position pos with respect to -1, i.e. beginning of the file thisl = fget(fh); thisl pos = ftell(fh) // store the new position fclose(fh) } } end
. win_stream ping 8.8.8.8 -n 10 --begin-- C:\Program Files (x86)\Stata12>ping 8.8.8.8 -n 10 Pinging 8.8.8.8 with 32 bytes of data: Reply from 8.8.8.8: bytes=32 time=5ms TTL=56 Reply from 8.8.8.8: bytes=32 time=7ms TTL=56 Reply from 8.8.8.8: bytes=32 time=5ms TTL=56 Reply from 8.8.8.8: bytes=32 time=6ms TTL=56 Reply from 8.8.8.8: bytes=32 time=8ms TTL=56 Reply from 8.8.8.8: bytes=32 time=5ms TTL=56 Reply from 8.8.8.8: bytes=32 time=7ms TTL=56 Reply from 8.8.8.8: bytes=32 time=7ms TTL=56 Reply from 8.8.8.8: bytes=32 time=6ms TTL=56 Reply from 8.8.8.8: bytes=32 time=8ms TTL=56 Ping statistics for 8.8.8.8: Packets: Sent = 10, Received = 10, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 5ms, Maximum = 8ms, Average = 6ms C:\Program Files (x86)\Stata12>echo --end-- --end--
Comment