JimmyBman Posted March 12, 2019 Share Posted March 12, 2019 Hey Guys I am struggling reading output from a command line system, I wish to make decisions based upon what is read. The first attempt at reading is successful but the second is just blank... Local $iPID= Run("C:\Program Files (x86)\PuTTY\plink.exe 10.xxx.xxx.xxx -ssh", "", @SW_HIDE, 2); If @error Or Not $iPID Then Exit Local $sStdOut = "" Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) ;$Message = StdoutRead($iPID) MsgBox(0, "attempting login", "Sending username",5) Sleep (10) StdinWrite($iPID, $username & @CRLF) Sleep (500) StdinWrite($iPID, $username & @CRLF) Local $sStdOut2 = "" Do Sleep(10) $sStdOut2 &= StdoutRead($iPID) Until @error $Message = StdoutRead($iPID) MsgBox(0, 'System says:', $sStdOut2) Link to comment Share on other sites More sharing options...
JimmyBman Posted March 13, 2019 Author Share Posted March 13, 2019 Sorry guys, I tidied up the code: Local $iPID= Run("C:\Program Files (x86)\PuTTY\plink.exe xx.xx.xx.xxx -ssh", "", @SW_HIDE, 2); If @error Or Not $iPID Then Exit Local $sStdOut = "" Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) ;$Message = StdoutRead($iPID) MsgBox(0, "attempting login", "Sending username",5) Sleep (10) StdinWrite($iPID, $username & @CRLF) Sleep (500) StdinWrite($iPID, $password & @CRLF) Local $sStdOut2 = "" Do Sleep(10) $sStdOut2 &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut2) Apologies, I tidied up the code: Local $iPID= Run("C:\Program Files (x86)\PuTTY\plink.exe 10.xxx.xxx.xxx -ssh", "", @SW_HIDE, 2); If @error Or Not $iPID Then Exit Local $sStdOut = "" Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) ;$Message = StdoutRead($iPID) MsgBox(0, "attempting login", "Sending username * password",5) Sleep (10) StdinWrite($iPID, $username & @CRLF) Sleep (500) StdinWrite($iPID, $password & @CRLF) Local $sStdOut2 = "" Do Sleep(10) $sStdOut2 &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut2) Link to comment Share on other sites More sharing options...
rm4453 Posted March 13, 2019 Share Posted March 13, 2019 52 minutes ago, JimmyBman said: Sorry guys, I tidied up the code: Local $iPID= Run("C:\Program Files (x86)\PuTTY\plink.exe xx.xx.xx.xxx -ssh", "", @SW_HIDE, 2); If @error Or Not $iPID Then Exit Local $sStdOut = "" Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) ;$Message = StdoutRead($iPID) MsgBox(0, "attempting login", "Sending username",5) Sleep (10) StdinWrite($iPID, $username & @CRLF) Sleep (500) StdinWrite($iPID, $password & @CRLF) Local $sStdOut2 = "" Do Sleep(10) $sStdOut2 &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut2) Apologies, I tidied up the code: Local $iPID= Run("C:\Program Files (x86)\PuTTY\plink.exe 10.xxx.xxx.xxx -ssh", "", @SW_HIDE, 2); If @error Or Not $iPID Then Exit Local $sStdOut = "" Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) ;$Message = StdoutRead($iPID) MsgBox(0, "attempting login", "Sending username * password",5) Sleep (10) StdinWrite($iPID, $username & @CRLF) Sleep (500) StdinWrite($iPID, $password & @CRLF) Local $sStdOut2 = "" Do Sleep(10) $sStdOut2 &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut2) Link to comment Share on other sites More sharing options...
JimmyBman Posted March 13, 2019 Author Share Posted March 13, 2019 Thanks so much RM That looks like it might solve things for me, I spent ages looking for examples Link to comment Share on other sites More sharing options...
rm4453 Posted March 13, 2019 Share Posted March 13, 2019 1 minute ago, JimmyBman said: Thanks so much RM That looks like it might solve things for me, I spent ages looking for examples No worries I just finished using it to check various devices on our network etc / auto compiling reports when devices error out etc... VERY USEFUL Link to comment Share on other sites More sharing options...
Gianni Posted March 13, 2019 Share Posted March 13, 2019 19 hours ago, JimmyBman said: I am struggling reading output from a command line system, I wish to make decisions based upon what is read. The first attempt at reading is successful but the second is just blank... ...when you use a loop like this: Do Sleep(10) $sStdOut &= StdoutRead($iPID) Until @error MsgBox(0, 'System says:', $sStdOut) the Until @error part works like this : the @arror occurs when you try to read with StdoutRead() from a process that is no more running. So if the error occurs it means that the process has finished and you have no more data to read. The whole otput is already in the $sStdOut variable. This kind of way to read from StdOut stream is good only when you run a command that will return a single output and then it will end. In this context the @error will mark the end of the job. But, if you have to interact with a running process, that is, get part of the output, send something with StdInWrite and so on, then checking @error is not ok, because @error doesn't means "I have finished to send my output", but it means "the process is no more running". You say: "but the second is just blank..." is because in the second reading loop, the plink.exe is no more running. JimmyBman 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
JimmyBman Posted March 13, 2019 Author Share Posted March 13, 2019 Hey Chimp That makes sense, my concern is that i'm sure it is! Perhaps my login code isn't actually logging into the device but killing the process... Link to comment Share on other sites More sharing options...
Gianni Posted March 13, 2019 Share Posted March 13, 2019 (edited) you can try this two tips to help with debugging1) use 0x8 as the fourth parameter of the run command (opt_flag) . In this way StOutRead will also capture any error messages. You will be able to better verify what is happening2) to see if after the first cycle plink.exe is still running, you can insert a ProcessExist () right after the cycle, something something like this: If Not ProcessExists($iPID) Then MsgBox(0, "Info", "Your process is over") P.S. also, if you want write to Input stream of the process with the StdInWrite() function, you have to enable the StdInput stream of the runned process by also enabling the $STDIN_CHILD(0x1) flag when you run your process, so, the fourth parameter of the run command shuld be 0x9 (that is $STDERR_MERGED (0x8) + $STDIN_CHILD (0x1) ) Edited March 14, 2019 by Chimp added a p.s. JimmyBman 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
JimmyBman Posted March 18, 2019 Author Share Posted March 18, 2019 Hey Chimp Thanks for your help above, I have only managed to get back to looking at this today. Getting further - I now have the correct statements for running the process. Now, while I can read from the system I can only do so when embedding that part inside a loop, a loop which I can't seem to manage correctly... Is there a simple trick I am missing, do I need to have a continuous loop running to keep reading output into a variable, at the moment it loops back to the start, THEN and only then can I see the variable being filled with output. but i'm stuck in a loop of sending credentials over and over. Sorry, this is probably really basic stuff to you and I do appreciate your help. expandcollapse popupLocal $iPID = Run("C:\Program Files (x86)\PuTTY\plink.exe 10.33.21.xxx -ssh", "", @SW_HIDE,$STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD) If Not ProcessExists($iPID) Then MsgBox(0, 'System says:', "process dead") EndIf If @error Or Not $iPID Then Exit Local $StdOut = "" While ProcessExists($iPID) $StdOut &= StdoutRead($iPID)&@CRLF ;If $stdOut >= True Then ExitLoop MsgBox(0, 'System says1:', $StdOut) MsgBox(0, "attempting login", "Sending username",5) Sleep (5000) StdinWrite($iPID, $username & @CRLF) Sleep (5000) StdinWrite($iPID, $password & @CRLF) Sleep (6000) StdinWrite($iPID, "TEST LINE" & @CRLF) Sleep (6000) MsgBox(0, 'System says2:', $StdOut) Sleep (6000) WEnd Link to comment Share on other sites More sharing options...
Bilgus Posted March 18, 2019 Share Posted March 18, 2019 (edited) Maybe this will help... Spoiler expandcollapse popup#include <AutoItConstants.au3> Global $iPID = Run("C:\Program Files (x86)\PuTTY\plink.exe 10.33.21.xxx -ssh", "", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD + $STDERR_CHILD) If Not ProcessExists($iPID) Then MsgBox(0, 'System says:', "process dead") EndIf If @error Or Not $iPID Then Exit Global $StdOut = "" Global $bLogin = False While ProcessExists($iPID) $StdOut = GrabStdOut($iPID) If @error Then ExitLoop ConsoleWrite('System says1: ' & $StdOut & @CRLF) If Not $bLogin Then $bLogin = Login($iPID, "USER1", "PA55W0RD") EndIf $StdOut = GrabStdOut($iPID) If @error Then ExitLoop ConsoleWrite('System says2: ' & $StdOut & @CRLF) Sleep(1000) WEnd Func Login($iPID, $sUsername, $sPassword, $iWait = 6000) ConsoleWrite("Attempting login, Sending username: " & $sUsername & @CRLF) StdinWrite($iPID, $sUsername & @CRLF) Sleep($iWait) StdinWrite($iPID, $sPassword & @CRLF) Sleep($iWait) Local $sStdOut = GrabStdOut($iPID, True) ;Only Peek stdout that means data is not erased If @error Then Return False ;Check if Login succeeded here.. set Return true if so.. Return True EndFunc ;==>Login Func GrabStdOut($iPID, $bPeek = False, $iRetrySecs = 5) ;$bPeek If True the function does not remove the read characters from the stream ;$iRetrySecs number of seconds to wait with no data before giving up Local $sStdOut = "", $iErr = 0, $iSecsLeft = $iRetrySecs If Not ProcessExists($iPID) Then $iErr = 0xBAD ; 2989 just something markedly different from error code from StdoutRead While $iErr = 0 ; If $bPeek Then $sStdOut = "" ;Comment out if you lose data $sStdOut &= StdoutRead($iPID, $bPeek) & @CRLF; $iErr = @error ;@error should be stored before running other commands ;If @extended = 0 Or $bPeek Then ;if $bPeek makes @extended continually return chars read If @extended = 0 Then; No characters were read If $iSecsLeft <= 0 Then ExitLoop ;Nothing to be read time to return output Sleep(1000) ; wait 1 second $iSecsLeft -= 1 ;Countdown Else; $iSecsLeft = $iRetrySecs ;Got data reset countdown EndIf; WEnd; Return SetError($iErr, StringLen($sStdOut), $sStdOut) ;Pass back data @extended contains string length EndFunc ;==>GrabStdOut Edited March 18, 2019 by Bilgus Link to comment Share on other sites More sharing options...
JimmyBman Posted March 18, 2019 Author Share Posted March 18, 2019 ❤️ working through it now, amazing, thank you so much! Link to comment Share on other sites More sharing options...
JimmyBman Posted March 28, 2019 Author Share Posted March 28, 2019 Hi @Bilgus Once again I wanted to thank you for the above code. It's helped me understand what was happening far more clearly. I have only just had time now to look at this again (my job allows for little time to be spent on this). I seem to be getting stuck inside the GrabStdOut function as below. I get as far as being prompted for the login details (which I can see on the console as read by the grab part the first time round). Then I send my creds, the main loop goes around again but I seem to get stuck on the "While $iErr = 0" line after that point. I have varied the $iRetrySecs to a few different settings to no avail... Func GrabStdOut($iPID, $bPeek = False, $iRetrySecs = 1) ;$bPeek If True the function does not remove the read characters from the stream ;$iRetrySecs number of seconds to wait with no data before giving up ConsoleWrite("1") Local $sStdOut = "", $iErr = 0, $iSecsLeft = $iRetrySecs ConsoleWrite("2") If Not ProcessExists($iPID) Then $iErr = 0xBAD ; 2989 just something markedly different from error code from StdoutRead ConsoleWrite("3") While $iErr = 0 ; ConsoleWrite("4") |||||||||||||||>>>>>> I seem to get endless 4s HERE <<<<<<<<<<||||||||||| If $bPeek Then $sStdOut = "" ;Comment out if you lose data $sStdOut &= StdoutRead($iPID, $bPeek) & @CRLF; $iErr = @error ;@error should be stored before running other commands ;If @extended = 0 Or $bPeek Then ;if $bPeek makes @extended continually return chars read If @extended = 0 Then; No characters were read If $iSecsLeft <= 0 Then ExitLoop ;Nothing to be read time to return output Sleep(1000) ; wait 1 second $iSecsLeft -= 1 ;Countdown Else; $iSecsLeft = $iRetrySecs ;Got data reset countdown EndIf; WEnd; Link to comment Share on other sites More sharing options...
Bilgus Posted March 28, 2019 Share Posted March 28, 2019 try uncommenting this line and comment out the one below If @extended = 0 Or $bPeek Then ;if $bPeek makes @extended continually return chars read ;If @extended = 0 Then; No characters were read Link to comment Share on other sites More sharing options...
JimmyBman Posted March 29, 2019 Author Share Posted March 29, 2019 Amazing, that worked!!!! Thank you so much 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