kjpolker Posted December 22, 2021 Posted December 22, 2021 (edited) As the title reads, if I already have a Command Prompt running how can I get the StdoutRead? As the helpfile mentions you need to call a Run function with the opt_flag $STDOUT_CHILD (Get's the standard output stream of the child process) but I am hung up on retrieving that PID if it was not called with Run. This is for a dedicated server, and when launching the server via AutoIt, has no issues but if the server is already up and running it would be beneficial to recognize that and begin capturing the stream without having to shut the server down and relaunch it with AutoIt. Secondly, some exe's launch a command line after a quick splash screen or user input, therefore Run does not allow you to obtain the correct Child Process as another example of wanting to retrieve the Stream of an already running process. I have looked through _WinAPI UDFs and found _WinAPI_GetParent but did not see anything for a Child (not that I believe this is the same thing anyways?). There must be a way? I can retrieve the handle and process ID of the Console Window but it will not return any output with StdoutRead because to my understanding it is just a graphic window from the console stream. Summary: Retrieve StdOutRead of an existing console application which was not called by AutoIt. Edited December 22, 2021 by kjpolker
kjpolker Posted December 22, 2021 Author Posted December 22, 2021 I know I have an option to highjack the text and paste it into my edit box but this is not the workaround I would like to use, if the above is achievable. It is very finicky, slow, and requires the command prompt window to enter focus. Example: #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiRichEdit.au3> $Form1 = GUICreate("Output", 618, 290, 192, 124) $Edit1 = _GUICtrlRichEdit_Create($Form1, "", 0, 0, 617, 289, BitOR($ES_AUTOVSCROLL,$WS_VSCROLL,$ES_MULTILINE,$ES_WANTRETURN)) GUICtrlSetData(-1, "") GUISetState(@SW_SHOW) HotKeySet("{F5}","getstream") ;Call function to get stream $handle = "" While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func getstream() $aWinList = WinList("[REGEXPTITLE:(?i)(.*cmd.*)]") ;find first handle of cmd window If UBound($aWinList) = 0 Then Return Else $handle = $aWinList[1][1] _GUICtrlRichEdit_AppendText($Edit1, "Handle: " & $handle & @CRLF) ;write handle to RichEdit WinActivate($handle) ;cmd must be activated to get contents ControlSend($handle,"", "", "! es{Enter}") ;brings up hidden menu to select and copy text. Alt+SPACE E S COPY $clip = ClipGet() ;Sets clipboard to variable _GUICtrlRichEdit_AppendText($Edit1, $clip & @CRLF) ;pastes clipboard EndIf EndFunc
ad777 Posted December 22, 2021 Posted December 22, 2021 kjpolker ; did you look at this :https://www.autoitscript.com/forum/topic/123970-dism-console-progress-using-stdoutread/?do=findComment&comment=861135 none
kjpolker Posted December 22, 2021 Author Posted December 22, 2021 I have not, but after reading through it appears a lot of that is for capturing the set amount of characters or chunk of the console and storing that information. Unless I am wrong, my example above mimics that although not as fluently and silent. If there isn't a method or UDF to essentially intercept the Console Application and utilize StdoutRead then I will probably conclude a server restart is required if I want to utilize my program at all.
kjpolker Posted December 23, 2021 Author Posted December 23, 2021 (edited) Food for thought, and I apologize if I should have just edited my post above to include this rather than comment new; but I am currently trying to understand what the $STDOUT_CHILD parameter is literally doing? So I can try and find a solution and do more research. Is it storing another value in the returned array of Run()? Is it setting the window properties of the STD I/O? Is it intercepting the I/O through a DLL call? I started to think about why I couldn't open a ComSpec window within AutoIt , stream the output, close AutoIt program, reopen AutoIt program and reattach it to the PID? Once AutoIt is closed the comspec window is in limbo especially if hidden and there is no way to view the stream, even if a /k and @SW_SHOW are used. It's basically executing whatever was called and you must force close it and reopen it with AutoIt. I even tried looking through the AutoIt directory for the guts of the Run functions, but unfortunately it is a built in function and does not require a a dependency (#include) to look through. I really am trying here, not looking for a free handout. Edited December 23, 2021 by kjpolker
junkew Posted January 2, 2022 Posted January 2, 2022 I doubt if its possible within Windows but if it is openprocess and duplicatehandle are probably phrases that can help if this is achievable https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output?redirectedfrom=MSDN FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
kjpolker Posted January 4, 2022 Author Posted January 4, 2022 Thank you for the post! Although I am unfamiliar with C++ that looks very interesting and maybe I can learn from it and get myself into C++ with the example provided.
markyrocks Posted January 4, 2022 Posted January 4, 2022 12 minutes ago, kjpolker said: Thank you for the post! Although I am unfamiliar with C++ that looks very interesting and maybe I can learn from it and get myself into C++ with the example provided. Those functions exist in autoit already. Just call this is probably the ticket. https://www.autoitscript.com/autoit3/docs/functions/StdinWrite.htm Pid can be had via getprocessid, or if it's an autoit script @autoitpid. You can always build a process information structure or use the tool help snap in my signature. Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
kjpolker Posted January 4, 2022 Author Posted January 4, 2022 I am familiar with those functions but to my understanding, and testing you must relay the $STDIN_CHILD parameter with the run function in order to capture the steam and write to it. If the process was not called via AutoIt then you cannot intercept the STDIN/OUT of the child process (command window).
markyrocks Posted January 4, 2022 Posted January 4, 2022 10 minutes ago, kjpolker said: I am familiar with those functions but to my understanding, and testing you must relay the $STDIN_CHILD parameter with the run function in order to capture the steam and write to it. If the process was not called via AutoIt then you cannot intercept the STDIN/OUT of the child process (command ca Can you write to the console? I only ask bc if you can then there's a problem with your implementation of the stdoutread function. It does not block (or pause) to receive a message. It won't even read the whole buffer so you basically have to call it continuously in a loop until you get the desired message. Creating a named pipe is the actual solution. That's that it was made for remote connection communication. Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
kjpolker Posted January 4, 2022 Author Posted January 4, 2022 (edited) Quote Creating a named pipe is the actual solution. That's that it was made for remote connection communication. I am not certain what this statement is referencing but it sounds like the right track. Essentially my tests have been to open up Command prompt window and interact with it (write to the console) while seeing if I can capture the output in a RichEdit GUI window. I get no results and I am certain I am attaching it to the correct PID, at least of the cmd.exe process running as I have referenced it to the task manager. That is where my small understanding comes into play of the console being a graphic display of input/output and is not the actual stream. The real world use I have is a dedicated server that shows input output of the status/backups/etc in a standard Command Window. Hope this helps. P.S. I have not tried writing to the console via AutoIt, only Read what is already there. Edited January 4, 2022 by kjpolker Answered question
markyrocks Posted January 4, 2022 Posted January 4, 2022 (edited) Create pipe won't work bc noone is listening for a message on the other side with your test. Make a cui script that opens up console, and THEN attempt to get the handle and write to it. I believe the system kernel owns the command prompt window and you probably won't ever get access to it. Easy IPC is clipput clipget Edited January 4, 2022 by markyrocks Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
kjpolker Posted January 4, 2022 Author Posted January 4, 2022 (edited) expandcollapse popup#include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiRichEdit.au3> $Form1 = GUICreate("Output", 618, 290, 192, 124) $Edit1 = _GUICtrlRichEdit_Create($Form1, "", 0, 0, 617, 289, BitOR($ES_AUTOVSCROLL,$WS_VSCROLL,$ES_MULTILINE,$ES_WANTRETURN)) GUICtrlSetData(-1, "") WinSetOnTop($Form1, "", 1) GUISetState(@SW_SHOW) HotKeySet("{F5}","stream") ;Call function to get stream $handle = "" Run("cmd.exe") While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func stream() $aWinList = WinList("[REGEXPTITLE:(?i)(.*cmd.*)]") ;find first handle of cmd window If UBound($aWinList) = 0 Then Return Else $handle = $aWinList[1][1] ;obtain handle of first cmd.exe window $apid = WinGetProcess($handle) ;obtain PID of handle _GUICtrlRichEdit_AppendText($Edit1, "Handle: " & $handle & @CRLF) ;write handle to RichEdit _GUICtrlRichEdit_AppendText($Edit1, "PID: " & $apid & @CRLF) ;write PID to RichEdit StdinWrite($apid, "Ping 127.0.0.1") ;Writes to console or executes? $timer = TimerInit() ;begin timer Local $output = "" Do Sleep(100) $output = StdoutRead($apid) _GUICtrlRichEdit_AppendText($Edit1, @CRLF & $output) ;write stream to RichEdit Until TimerDiff($timer) > 5000 ;read stream until 5 seconds has passed EndIf EndFunc I know there are other ways to test but I had the majority of this available from previous tests so I changed it up to simply launch a console window and attempt to write/read. I get empty lines as a result. Is this what you had in mind and you expected it to fail as per your last sentence? Edited January 4, 2022 by kjpolker
markyrocks Posted January 5, 2022 Posted January 5, 2022 5 hours ago, kjpolker said: I know there are other ways to test but I had the majority of this available from previous tests so I changed it up to simply launch a console window and attempt to write/read. I get empty lines as a result. Is this what you had in mind and you expected it to fail as per your last sentence? I was kinda busy when i wrote the last reply. I meant make a "dummy" script that all it does is start running and loop forever with a sleep in there so it doesn't hog the cpu . Then compile that script checking the box that says create CUI instead or GUI exe. That means the program will open the console window automatically. you can even have it echo a msg every few seconds or something. Once you have a separate process running with a console use it to practice hooking into the running process. the cmd prompt is a system process and not going to be easy to manipulate. You don't even have to use the console you can just open a temp file mapped to memory and use that to send messages back and forth. Let me see if I can make something happen with this. Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
markyrocks Posted January 5, 2022 Posted January 5, 2022 (edited) You could try using a dll call to ...https://docs.microsoft.com/en-us/windows/console/freeconsole which would be as simple as. This code is untested and barely checked for spelling, syntax etc $res = DllCall("Kernel32.dll","bool","FreeConsole","none") if not isarray($res) or not $res[0] then exit ;failed THEN you can attach to the second threads console . using... https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_AttachConsole.htm. thats the best i got. Edited January 5, 2022 by markyrocks Spoiler "I Believe array math to be potentially fatal, I may be dying from array math poisoning"
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