luckyluke Posted July 22, 2017 Posted July 22, 2017 Hello, Im trying to read the output from CMD using Dllcall, here is my code: expandcollapse popup#include <WinAPI.au3> #include <array.au3> Global Const $STD_OUTPUT_HANDLE = -11 Global Const $_CONSOLE_SCREEN_BUFFER_INFO = _ "struct;int dwSizeX;" & _ "short dwSizeY;" & _ "short dwCursorPositionX;" & _ "short dwCursorPositionY;" & _ "short wAttributes;" & _ "short Left;" & _ "short Top;" & _ "short Right;" & _ "short Bottom;" & _ "short dwMaximumWindowSizeX;" & _ "short dwMaximumWindowSizeY;endstruct" $pCmd = Run( "cmd.exe" ) Sleep(1000) $hCmd = WinGetHandle("") ConsoleWrite('handle:' & $hCmd & @CRLF) $aRet = DllCall("kernel32.dll", "int", "AttachConsole", "dword", $pCmd) ;_ArrayDisplay($aRet) If $aRet[0] <> 0 Then $vHandle_data='' $vHandle='' $vHandle_data = DllStructCreate($_CONSOLE_SCREEN_BUFFER_INFO) ; Screen Buffer structure $aRet1 = DllCall("kernel32.dll", "hwnd", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE) if not @error Then $vHandle = $aRet1[0] $aRet = DllCall("kernel32.dll", "int", "GetConsoleScreenBufferInfo", "hwnd", $vHandle, _ "ptr", $vHandle_data) MsgBox(0, '1',DllStructGetData($vHandle_data, 'dwSizeX') & _WinAPI_GetLastErrorMessage()) EndIf It did not work, i got the message 'The handle is invalid'. Please help? Thank you in advance!
Developers Jos Posted July 22, 2017 Developers Posted July 22, 2017 Why not simply use the standard supported StdoutRead() & StderrRead() in combination with Run()? Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past.
TheDcoder Posted July 22, 2017 Posted July 22, 2017 Or you can also give Process UDF a try, you can get the output with a single line of code. EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion
luckyluke Posted July 23, 2017 Author Posted July 23, 2017 8 hours ago, Jos said: Why not simply use the standard supported StdoutRead() & StderrRead() in combination with Run()? Jos Yes, that is the common way, i tried it, but it does not capture all output from the cmd. That why i want to try with console attach 7 hours ago, TheDcoder said: Or you can also give Process UDF a try, you can get the output with a single line of code. Your code is using the Stdreadout, i tried it before but it did not work.
TheDcoder Posted July 23, 2017 Posted July 23, 2017 Are you trying to read output directly from cmd.exe? EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion
luckyluke Posted July 23, 2017 Author Posted July 23, 2017 49 minutes ago, TheDcoder said: Are you trying to read output directly from cmd.exe? Do you mean read from cmd.exe using StdoutRead, yes it can read output from cmd but not all things. I have an other program run using CMD, it will out the result to CMD, then i used StdoutRead to read from cmd, but can not get all result from there.
TheDcoder Posted July 23, 2017 Posted July 23, 2017 (edited) 1 hour ago, luckyluke said: it can read output from cmd but not all things I suspect that the program which outputs to the CMD is also using StdErr stream. You should try using the $STDERR_MERGED flag, the _Process_RunCommand function from Process UDF automatically does that for you by default Edited July 23, 2017 by TheDcoder EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion
luckyluke Posted July 23, 2017 Author Posted July 23, 2017 6 minutes ago, TheDcoder said: I suspect that the program which outputs to the CMD is also using StdErr stream. You should try using the $STDERR_MERGED flag, the _Process_RunCommand function from Process UDF automatically does that for you by default yes, i tried, but not work. I see that if i close the program then it will show the message in the output. but if i run it from cmd, the message appears even when program is running.
TheDcoder Posted July 23, 2017 Posted July 23, 2017 (edited) 7 minutes ago, luckyluke said: but if i run it from cmd, the message appears even when program is running. If that is the case, then you can try calling the program from instead of directly calling it. You can do it like this in my UDF: $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, $PROCESS_COMMAND & 'path_to_your_program.exe') ; This will execute cmd.exe which will run your program This way, cmd.exe acts like a proxy between the AutoIt script and the program. You should be able to read all output given to cmd.exe if you use the above code snippet Edited July 23, 2017 by TheDcoder Add $sOutput to the code snippet EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion
Trong Posted July 23, 2017 Posted July 23, 2017 I have a look at Process UDF, the code seems complicated. Try this simple one: expandcollapse popupLocal $iCommand = "ping google.com" _RunCmd($iCommand) _RunCmd_GetStdOut($iCommand) Func _RunCmd($sCommand) ConsoleWrite("+ Execute: " & $sCommand & @CRLF) Local $sOutput = '', $iPID = Run('"' & @ComSpec & '" /c ' & '"' & $sCommand & '"', '', @SW_HIDE, 0x6) If Not $iPID Then Return SetError(1, 0, '') Do $sOutput &= StdoutRead($iPID) Until @error Do $sOutput &= StderrRead($iPID) Until @error ConsoleWrite("" & $sOutput & @CRLF) ConsoleWrite("- -------------------------------------------------------------" & @CRLF) Return $sOutput EndFunc ;==>_RunCmd Func _RunCmd_GetStdOut($sCommand, $sDir = '', $iType = 0x6, $bShow = False, $iDelay = 50) ConsoleWrite("+ Execute: " & $sCommand & @CRLF) Local $sTMP = '', $sOutput = '' Local $iPID = Run('"' & @ComSpec & '" /c ' & '"' & $sCommand & '"', $sDir, $bShow ? @SW_SHOW : @SW_HIDE, $iType) If Not $iPID Then Return SetError(1, 0, '') While 1 $sTMP = StdoutRead($iPID, False, False) If @error Then ExitLoop 1 If $sTMP <> "" Then $sTMP = StringReplace($sTMP, @CR & @CR, '') $sOutput &= $sTMP ConsoleWrite($sTMP) Sleep($iDelay) EndIf WEnd While 1 $sTMP = StderrRead($iPID, 0, 0) If @error Then ExitLoop If $sTMP <> "" Then $sTMP = StringReplace($sTMP, @CR & @CR, '') $sOutput &= $sTMP ConsoleWrite($sTMP) Sleep($iDelay) EndIf WEnd ConsoleWrite("- -------------------------------------------------------------" & @CRLF) Return $sOutput EndFunc ;==>_RunCmd_GetStdOut luckyluke 1 Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal
Developers Jos Posted July 23, 2017 Developers Posted July 23, 2017 4 hours ago, luckyluke said: yes, i tried, but not work. I see that if i close the program then it will show the message in the output. but if i run it from cmd, the message appears even when program is running. Show your code and info on the program running so we can see what might be the issue. Jos SciTE4AutoIt3 Full installer Download page - Beta files Read before posting How to post scriptsource Forum etiquette Forum Rules Live for the present, Dream of the future, Learn from the past.
luckyluke Posted July 23, 2017 Author Posted July 23, 2017 7 hours ago, TheDcoder said: If that is the case, then you can try calling the program from instead of directly calling it. You can do it like this in my UDF: $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, $PROCESS_COMMAND & 'path_to_your_program.exe') ; This will execute cmd.exe which will run your program This way, cmd.exe acts like a proxy between the AutoIt script and the program. You should be able to read all output given to cmd.exe if you use the above code snippet This code will get the output when the program ends. But i want to get the status when the program is running. 3 hours ago, VIP said: I have a look at Process UDF, the code seems complicated. Try this simple one: Yes, i found it and tried it before. But the code actually get the output after the program exit. I want to get the console while the program is running. this is my code: the code will open the CMD and run "python ui.py" then get the output from console. expandcollapse popup#include 'array.au3' ;#include "UIAWrappers.au3" Global $DOS, $timer, $whd $live_file = IniRead(@ScriptDir & '\config.ini', 'py_run', 'live_file', '') $prediction_file = IniRead(@ScriptDir & '\config.ini', 'py_run', 'prediction_file', '') $training_file = IniRead(@ScriptDir & '\config.ini', 'py_run', 'training_file', '') $wait_time = IniRead(@ScriptDir & '\config.ini', 'py_run', 'wait_time', 6) FileDelete(@ScriptDir & '\pyConsole.txt') startPY() Sleep(1000) $checker = 1 $i = 1 While 1 $tmp = ControlGetText('python.exe', '', 'Button1') if StringInStr($tmp, 'check online for a solution') Then WinClose('python.exe') Sleep(3000) startPY() EndIf ;~ Sleep(50) ;; no need to go at full speed here. ;~ $sOutput='' ;~ While 1 ;~ $sOutput &= StdoutRead($DOS, False, False) ;~ If @error Then ;~ ExitLoop ;~ EndIf ;~ Sleep(10) ;~ ConsoleWrite($sOutput) ;~ WEnd $Message = StdoutRead($DOS) ;; ditched peek parameter + changed "=" to "&=" ... No more endless loop. if @error Then restartPY() startPY() EndIf ;$sOutput = StderrRead($DOS) ;ConsoleWrite($i & ':' & $sOutput & ',' & StringLen($sOutput) & @CRLF) ConsoleWrite($i & ':' & $Message & ',' & StringLen($Message) & @CRLF) $i=$i+1 if StringLen($Message)>2 and StringInStr($Message, @CRLF) Then ConsoleWrite('i:' & $i & ',' & $Message & @CRLF) ;$i=$i+1 if StringInStr($Message, ',') Then $tmp = StringSplit($Message, @CRLF) ;_ArrayDisplay($tmp) if not @error Then for $j = 1 to UBound($tmp)-1 if StringInStr($tmp[$j], ',') Then $file = FileOpen(@ScriptDir & '\pyConsole.txt', 1) FileWrite($file, $tmp[$j] & @CRLF) FileClose($file) EndIf Next EndIf EndIf $checker=1 Else $checker = $checker+1 ;ConsoleWrite('checker:' & $checker & @CRLF) if $checker=10 Then $timer = TimerInit() EndIf EndIf if $checker>=10000 Then $atime = TimerDiff($timer)/1000 if not @error Then if $atime>Number($wait_time) Then restartPY() startPY() EndIf EndIf EndIf if @error then exitloop WEnd Func restartPY() Do if WinExists('C:\Windows\system32\cmd.exe') then WinClose('C:\Windows\system32\cmd.exe') Else ExitLoop EndIf Until WinExists('C:\Windows\system32\cmd.exe')=0 WinActivate('Predictive model 1.0') Sleep(500) WinClose('Predictive model 1.0') WinWait('Confirm Exit', '', 3) WinActivate('Confirm Exit') WinMove('Confirm Exit', '', 0, 0) Sleep(500) if WinExists('Confirm Exit') then MouseClick('left', 109,94) Sleep(4000) EndFunc Func startPY() $CMD = 'cd ' & @DesktopDir & '\Predictive_model && ' & _ 'python ui.py' $DOS = Run(@ComSpec & ' /C ' & $CMD, @ScriptDir, @SW_SHOW, $STDOUT_CHILD+$RUN_CREATE_NEW_CONSOLE) ;$DOS = Run(@ComSpec & ' /C ' & $CMD, @ScriptDir, @SW_SHOW, $STDIN_CHILD + $STDERR_MERGED) ConsoleWrite($DOS & @CRLF) $mtitle = 'Predictive model 1.0' WinWait($mtitle, '', 5000) ;Sleep(5000) WinMove($mtitle, '', 0, 0) Sleep(1000) ;=====================================set value to GUI================================================= ;live file ;_UIA_Action("Title:=;controltype:=UIA_EditControlTypeId;class:=","setfocus") ;_UIA_Action("Title:=;controltype:=UIA_EditControlTypeId;class:=","setValue using keys", "C:\Users\Administrator\Desktop\Sabrina Betting\LV1.txt") WinActivate($mtitle) Sleep(1000) MouseClick('left', 345,87) Send("^a") Sleep(500) Send($live_file & '11') ;prediction file WinActivate($mtitle) Sleep(1000) MouseClick('left', 345,200) Send("^a") Sleep(500) Send($prediction_file) ;use control click WinActivate($mtitle) Sleep(1000) MouseClick('left', 345,234) Send("^a") Sleep(500) Send($training_file) ;click start button ;~ Local $oP1=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=Predictive model 1.0;controltype:=UIA_WindowControlTypeId;class:=QWidget", $treescope_children) ;~ Local $oP0=_UIA_getObjectByFindAll($oP1, "Title:=;controltype:=UIA_CustomControlTypeId;class:=", $treescope_children) ;~ Local $oUIElement=_UIA_getObjectByFindAll($oP0, "title:=Start;ControlType:=UIA_ButtonControlTypeId", $treescope_subtree) ;~ _UIA_action($oUIElement,"focus") ;~ _UIA_action($oUIElement,"click") WinActivate($mtitle) Sleep(1000) MouseClick('left', 593,301) Sleep(3000) EndFunc
TheDcoder Posted July 23, 2017 Posted July 23, 2017 1 minute ago, luckyluke said: This code will get the output when the program ends. But i want to get the status when the program is running. In that case you can use $PROCESS_RUN instead of $PROCESS_RUNWAIT. Refer to the Example.au3 script for more details luckyluke 1 EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time) DcodingTheWeb Forum - Follow for updates and Join for discussion
luckyluke Posted July 23, 2017 Author Posted July 23, 2017 4 hours ago, TheDcoder said: In that case you can use $PROCESS_RUN instead of $PROCESS_RUNWAIT. Refer to the Example.au3 script for more details ok, i will check it. thank you
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