DaveF Posted December 10, 2004 Share Posted December 10, 2004 I finished an alpha version this morning, I hope to have something to submit to Jon this weekend (hmm, sounds like what I said about default args...) Uses the functionality of CreateProcess to redirect the standard handles.Sample code & output:AutoItSetOption("CaptureRunStdout", 1) Run("net.exe users", @SystemDir) While 1 $line = FileReadLine(@RunStdout) If @error = -1 Then ExitLoop MsgBox(0, "Line read:", $line) WendThere's still a question of what should happen if you run a second process before you've read all the output from the first. I think the easiest thing from the implementation side would be to junk the last pipe and its unread output and create a new pipe.Please let me know your thoughts.Dave Fulgham Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
this-is-me Posted December 10, 2004 Share Posted December 10, 2004 Looks like it could only be a RunWait thing, since just using Run could cause so many problems. Who else would I be? Link to comment Share on other sites More sharing options...
DaveF Posted December 10, 2004 Author Share Posted December 10, 2004 Looks like it could only be a RunWait thing, since just using Run could cause so many problems.<{POST_SNAPBACK}>What kind of problems were you thinking of?RunWait() could cause problems of its own; the redirected STDOUT pipe has a limited size, if the child process writes it full then the child process should block (suspend) and wait until the process on the other end of the pipe (the parent) reads some of the characters out to make room for another write operation. If you've used RunWait() for your child process then your script is waiting for the child to return before continuing (to do a FileRead() etc.) and the child is waiting for your script to read something off the pipe before continuing, so you're in a deadlock... Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
this-is-me Posted December 10, 2004 Share Posted December 10, 2004 I thought you meant that if you called another exe while already reading the pipe of the original one, that it could cause some major internal code problems. Who else would I be? Link to comment Share on other sites More sharing options...
KenE Posted December 10, 2004 Share Posted December 10, 2004 (edited) Dave, I see what forum I'm in now, so I assume that this is something that doens't exist in AutoIt yet. I have an immediate use for what you are currently working on. Would it be possible to get the code that you are using to use in my script? I simply need to capture one line from STDOUT and basically, it's no more complex than the example you showed earlier. Please let me know. Thanks! Edited March 18, 2005 by KenE Link to comment Share on other sites More sharing options...
DaveF Posted December 10, 2004 Author Share Posted December 10, 2004 Dave,I see what forum I'm in now, so I assume that this is something that doens't exist in AutoIt yet. I have an immediate use for what you are currently working on. Would it be possible to get the code that you are using to use in my script? I simply need to capture one line from STDOUT and basically, it's no more complex than the example you showed earlier. Please let me know. Thanks!Ken Ellefson<{POST_SNAPBACK}>I code recreationally at home, I don't have access to my source from where I am now.In the past I've had to redirect output of a child process to a file and then read that back in from AutoIt, I'll see if I've got an example that I can post... Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
DaveF Posted December 10, 2004 Author Share Posted December 10, 2004 (edited) Here go, example that gets the state of a service: expandcollapse popupFunc AssessSvc() ; Capture reports of the running state and current config of the service ; to a file. Note that the 2nd command uses >> to append output vs. > . RunWait(@ComSpec & ' /c c:\windows\system32\sc.exe interrogate WZCSVC > '_ & @TempDir & '\wzc-state.txt', @SystemDir, @SW_HIDE) RunWait(@ComSpec & ' /c c:\windows\system32\sc.exe qc WZCSVC >> '_ & @TempDir & '\wzc-state.txt', @SystemDir, @SW_HIDE) ; Walk through the output file. If FileExists(@TempDir & "\wzc-state.txt") Then ; Assume that the service is stopped. $ISRUNNING = 0 ; Open file for reading. $OURFILE = FileOpen(@TempDir & '\wzc-state.txt', 0) ; Loop to read lines from the file. While 1 $OURLINE = FileReadLine($OURFILE) ; FileReadLine sets @error to -1 at end-of-file, so break out of the loop If @error = -1 Then ExitLoop ; If we find STATE and RUNNING then the service is started, so set ISRUNNING If (StringInStr($OURLINE, "STATE")) And (StringInStr($OURLINE, "RUNNING")) Then $ISRUNNING = 1 EndIf ; On the first call to this function, determine if startup type is already ; on demand and adjust so that the checkbox will be checked accordingly If (StringInStr($OURLINE, "START_TYPE")) And (Not IsInt($ISMANUAL)) Then If StringInStr($OURLINE, "DEMAND_START") Then $ISMANUAL = 1 $NOAUTORUNSVC = 1 Else $ISMANUAL = 0 EndIf EndIf Wend ; Close the output file. FileClose($OURFILE) Else ; Couldn't find the output report file. ErrorMsg("Can't find SVC report file!") EndIf EndFunc ;==>AssessSvc Edit: The code above was composed using the SciTE editor w/ Tidy.AU3 . Thanks, JdeB Edited December 10, 2004 by DaveF Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
Chris_1013 Posted December 10, 2004 Share Posted December 10, 2004 This is cool, and is something I'd love to be able to do, since it removes the reliance on a temporary file or external utility, but I just wonder whether the implementation makes sense. I would've thought some way of redirecting STDOUT to a variable of your choosing would be better. Note: I'm not saying I have the answer, just thinking out loud. Link to comment Share on other sites More sharing options...
DaveF Posted December 10, 2004 Author Share Posted December 10, 2004 This is cool, and is something I'd love to be able to do, since it removes the reliance on a temporary file or external utility, but I just wonder whether the implementation makes sense. I would've thought some way of redirecting STDOUT to a variable of your choosing would be better.Note: I'm not saying I have the answer, just thinking out loud.<{POST_SNAPBACK}>In C++ one treats the STDIN/STDOUT/STDERR streams in a file like way (same functions to read and write that you'd use for files), so it just seemed natural to carry that over to AutoIt.If you dumped multiline child output to a variable you'd still have to search in some way for the line of data you wanted to retrieve, where with FileReadLine() you can tell it what line to read from... Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
DaveF Posted December 10, 2004 Author Share Posted December 10, 2004 Dave,Thanks for the code. I've tried your example, and several other variations, but no matter what I do, it's not working. I get the text file created in the Temp directory, but it's always empty. When I run the exact same command from the command line, I get the result in the text file, as expected. Maybe it's the app that I'm running? I have the C source for the app that I'm trying to capture from, if you'd like to see it.<{POST_SNAPBACK}>Are you using a command shell to run your app? You have to do so if you're using the > redirect... (cf. my example) Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
KenE Posted December 10, 2004 Share Posted December 10, 2004 (edited) Here's the code I'm using: FileChangeDir(EnvGet("LOGONSERVER"), & '\NETLOGON\') $result=RunWait(@ComSpec & ' /c NTNAME.EXE %USERNAME% > ' & @TempDir & '\OTHERPC.TXT', @SystemDir, @SW_HIDE) If $result <> 1 Then Exit Else FileChangeDir(EnvGet("TEMP")) $file = FileOpen("OTHERPC.TXT", 0) ; Check if file opened for reading OK If $file = -1 Then Exit EndIf ; Read in lines of text until the EOF is reached $line = FileReadLine($file) If @error = -1 Then Exit EndIf FileClose($file) Edited December 13, 2004 by KenE Link to comment Share on other sites More sharing options...
this-is-me Posted December 10, 2004 Share Posted December 10, 2004 You may need to double quote (") the output file and directory. Who else would I be? Link to comment Share on other sites More sharing options...
Angel Posted December 11, 2004 Share Posted December 11, 2004 DaveF, this looks really cool, thanks a lot! However, do you think that it will ever be possible to read the contents of an existing console window or of a console window that is not directly open by autoit? For instance, let's say that I call a batch file from autoit, or perhaps another autoit executable program and it creates an additional stand alone command window. Would it be possible to read its output after doing a WinActivate(....) for instance? It does not seem so as you are using CreateProcess... Angel Link to comment Share on other sites More sharing options...
sugi Posted December 11, 2004 Share Posted December 11, 2004 (edited) In C++ one treats the STDIN/STDOUT/STDERR streams in a file like way (same functions to read and write that you'd use for files), so it just seemed natural to carry that over to AutoIt.If you dumped multiline child output to a variable you'd still have to search in some way for the line of data you wanted to retrieve, where with FileReadLine() you can tell it what line to read from...<{POST_SNAPBACK}>So what about a mix of Run() and FileOpen() then? Maybe something like this:$fd=RunPipe('net localgroup Administrators', @SystemDir, @SW_HIDE) if $fd <> -1 Then $x = FileReadLine($fd) While not @error MsgBox(0, 'Line', $x) $x = FileReadLine($fd) WEnd EndIfMaybe it would also be possible to write to this fd with FileWrite then to interact with the program?EDIT: Just thought about the error code from the program that is run. I don't know if it's possible but maybe RunPipe could return an array consisting of the file descriptors for the program (stdin, stdout, stderr) and a placeholder for the error code? So you could still get the error code this way:$x=RunPipe('Net localgroup Administrators', @SystemDir, @SW_HIDE) if not @error Then $line = FileReadLine($x[1]) if not @error Then MsgBox(0, 'First Line', $line) FileWriteLine($x[0], 'Some input to send to the program. Well, net localgroups does not need any.') ; Now wait for program to end FileClose($x[1]) $errorcode = $x[3] EndifI think $x should look like this:$x[0] = STDIN$x[1] = STDOUT$x[2] = STDERR$x[3] = error code that's returned by the programOf course $x[3] should never be read before the program exited (that's the reason for the FileClose($x[1]). The script should pause there until the program finished).I don't know if all of my ideas are possible or even sensible because I have only written very simple programs in C/C++ for now but they're here for discussion. Edited December 11, 2004 by sugi Link to comment Share on other sites More sharing options...
DaveF Posted December 11, 2004 Author Share Posted December 11, 2004 Angel, I believe I saw a post regarding interaction with console windows elsewhere in the forum. Sugi, thanks for the post. After having the day to experiment and review I see that it will be easier to pipe the entirety of the standard output to a string and then access that from a macro like @RunStdout. Reconciling the difference between the HANDLE-based Win32 functions and the FILE* -based standard library functions was causing an ever-growing code bloat and duplication for the desired result. By just copying to output to a string and closing the pipe it won't be an issue if you run another process, @RunStdout just gets updated with the output of each new Run(). Since you do have access to the STDIN pipe through the same method I'm using it would be possible to pipe STDIN to the child process, but it would probably be best to prepare what you wanted to pipe in (like @RunStdin = "blah") before calling Run() because the child process would be paused until the script's end of the STDIN pipe was written to and closed, which would again run a risk of deadlock if you had used RunWait() to run your child process... STDERR could be captured in its own string exactly the way that STDOUT will be, or both can be directed to the same pipe and string. Options can be added to configure these things if there's enough interest; I may put together a poll about it. Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
kanumi Posted December 13, 2004 Share Posted December 13, 2004 If one can only access the output after program's execution and provide the input before, there will be no possibility to interact with the program depending on it's output. For no-wait runs i would prefer having the chance to act interactively. For RunWait it is clearly not needed any Output mapped to Variable would be perfect. I know, from own experience, that it can be a little bit hard to get and transfer the output/input stream without unwanted buffering. Link to comment Share on other sites More sharing options...
DaveF Posted December 14, 2004 Author Share Posted December 14, 2004 I've got the initial version done. It captures both standard output and the standard error streams to a variable during the course of the Run() process. The user can access the variable after the Run() returns to get the output of the child process. I'm starting a poll to see what functionality would be used if it was present. Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now