Jump to content

$STDIN_CHILD - really basic question


ahha
 Share

Recommended Posts

I have a really basic question.  I'm trying to tap into $STDIN_CHILD for cmd.exe and the simple script below is not working.

I'm getting the cmd.exe prompt in the SciTE console and no dir listing in the cmd.exe window.  I've tried variations and am stuck.  What am I doing wrong?

#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>

$iPID = Run("C:\Windows\system32\cmd.exe", @SystemDir, @SW_MAXIMIZE, $STDIN_CHILD)
MsgBox($MB_TOPMOST, "Debug", "$iPID = '" & $iPID & "'" & @CRLF & _
    "Look at console window in SciTE - why does it have cmd.exe output?  I only tapped STDIN, not STDOUT.")

StdinWrite($iPID, "dir{ENTER}")
If @error Then Exit MsgBox(0, "ERROR", "Error using StdWrite.")
;why is the directory listing not going to the cmd.exe window?  Where is it going?

MsgBox($MB_TOPMOST, "Paused", "Click OK to exit program.")
Exit

 

Link to comment
Share on other sites

try this Function for CMD:

;~ #RequireAdmin

#include <File.au3>
If @OSArch = "X64" And Not @AutoItX64 Then _Wow64FsRedirection(0)

Local $output= _RunCmd_GetOutput("dir")
MsgBox(0, "", $output)
Local $output=_StreamCMD("ping 8.8.8.8")
MsgBox(0, "", $output)

Func _RunCmd_GetOutput($sCommand)
    ConsoleWrite("+Execute: " & $sCommand & @CRLF)
    Local $sOutput = '', $iPID = Run('"' & @ComSpec & '" /c ' & $sCommand, '', @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    Do
        $sOutput &= StdoutRead($iPID)
    Until @error
    Do
        $sOutput &= StderrRead($iPID)
    Until @error
    ConsoleWrite($sOutput&@CRLF)
    Return $sOutput
EndFunc   ;==>_RunCmd


Func _StreamCMD($sCMD, $sCallBackFunction = Default, $WorkingDir = Default, $iStreamType = Default, $iShowFlag = Default, $iDelay = Default)
    If StringStripWS($sCMD, 8) = "" Then Return ""
    If $sCallBackFunction = Default Then $sCallBackFunction = "ConsoleWrite"
;~  If $WorkingDir = Default Then $WorkingDir = @SystemDir ;@WindowsDir & '\System32'
    If $WorkingDir = Default Then $WorkingDir = @WindowsDir & '\System32'
    If $iStreamType = Default Then $iStreamType = $STDERR_CHILD + $STDOUT_CHILD
    If $iShowFlag = Default Then $iShowFlag = False
    If $iDelay = Default Then $iDelay = 250
    ConsoleWrite("! Execute: " & $sCMD & @CRLF)
    Local $sTMP = '', $sSTD = '', $sCOM = '"' & @WindowsDir & '\System32\cmd.exe"' & ' /c ' & $sCMD
;~  Local $sTMP = '', $sSTD = '', $sCOM = @ComSpec & ' /c ' & $sCMD
    Local $iWin = $iShowFlag ? @SW_SHOW : @SW_HIDE
    Local $iPID = Run($sCOM, $WorkingDir, $iWin, $iStreamType)
    While 1
        $sTMP = StdoutRead($iPID, False, False)
        If @error Then ExitLoop
        If $sTMP <> "" Then
            $sTMP = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP
            Call($sCallBackFunction,$sTMP)
;~          ConsoleWrite($sTMP)
            Sleep($iDelay)
        EndIf
    WEnd
    While 1
        $sTMP = StderrRead($iPID, False, False)
        If @error Then ExitLoop
        If $sTMP <> "" Then
            $sTMP = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP
            Call($sCallBackFunction,$sTMP)
;~          ConsoleWrite($sTMP)
            Sleep($iDelay)
        EndIf
    WEnd
;~  If $sSTD <> "" Then ConsoleWrite(@CRLF)
    Return SetError(@error, @extended, $sSTD)
EndFunc   ;==>_StreamCMD
; * -----:|  Dao Van Trong - TRONG.WIN

Func _Wow64FsRedirection($state)
    If @OSArch = "X64" Then
        If $state Then
            ;DllCall("kernel32.dll", "int", "Wow64EnableWow64FsRedirection", "int", 1)
            DllCall("kernel32.dll", "int", "Wow64RevertWow64FsRedirection", "int", 0)
        Else
            ;DllCall('kernel32.dll', 'boolean', 'Wow64EnableWow64FsRedirection', 'boolean', False)
            DllCall("kernel32.dll", "int", "Wow64DisableWow64FsRedirection", "int", 0)
        EndIf
        If @error Then Return SetError(1, 0, 0)
        Return 1
    EndIf
EndFunc   ;==>_Wow64FsRedirection

 

Edited by VIP

Regards,
 

Link to comment
Share on other sites

VIP,

I understand most of your code but it looks like it's mainly capturing the STDOUT.  I do not see a single STDIN.  I'm trying to open cmd.exe and send it commands via STDIN.  DIr was just an example to show that the output is not going to the cmd.exe window when I only tapped into STDIN.  I do not understand why my simple code is not working.

ahha

Link to comment
Share on other sites

55 minutes ago, ahha said:

StdinWrite($iPID, "dir{ENTER}")

First this statement is wrongly formulated.  Does not work like a send function, so you should do StdinWrite($iPID, "dir" & chr(13))

Second  I believe cmd.exe doesn't do ConsoleRead for security reasons.

Edited by Nine
Link to comment
Share on other sites

Nine - thanks for that information.  I clipped it just to "dir" to see if it would show in the cmd.exe window and no it does not.  So it looks like cmd.exe does not accept STDIN.

FrancescoDiMuro - my example of Dir has misdirected some answers - I should have used the example "help".  I'm simply trying to get cmd.exe to take STDIN.  It appears from Nine that cmd.exe may not accept STDIN.

Can anyone confirm that cmd.exe does not accept STDIN?

Link to comment
Share on other sites

You could just write your commands during execution, for example:

#include <AutoItConstants.au3>

;~ Concatenating Commands
;~ & Execute command
;~ && Execute only if previous command in the string was successful

;~ Display Output
Run(@ComSpec & ' /k Echo Directory List for: "' & @ProgramFilesDir & '"&Echo.&C:&&Cd\&&Cd "' & @ProgramFilesDir & '"&&Dir')

;~ Run Hidden and Write Output to Scite
Local $iCmdPid = Run(@ComSpec & ' /c Echo Directory List for: "' & @WindowsDir & '"&Echo.&C:&&Cd\&&Cd "' & @WindowsDir & '"&&Dir', @WindowsDir & "\System32", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
Local $sOutput = ""
While 1
    $sOutput &= StdoutRead($iCmdPid)
    If @error Then ExitLoop
WEnd
While 1
    $sOutput &= StderrRead($iCmdPid)
    If @error Then ExitLoop
WEnd
ConsoleWrite($sOutput & @CRLF)

 

Link to comment
Share on other sites

40 minutes ago, ahha said:

If I simply wanted to send "1234" to the cmd.exe window using STDIN - is that possible?

@ahha

Yes.  Here's a very simple example.  If you run it in SCITE, you will see the output in the output pane.

#include <Constants.au3>

example()

Func example()
    Local $iPid = Run(@ComSpec, "", Default, $STDIN_CHILD)
    StdinWrite($iPid, "CD \" & @CRLF)
    StdinWrite($iPid, "Dir" & @CRLF)
    StdinWrite($iPid, "1234" & @CRLF)
EndFunc

 

Link to comment
Share on other sites

TheXman,

It looks like there is no way to keep the cmd.exe window open and show the STDIN.  I changed it to this.  I'd prefer to see the output in the cmd.exe window since I did not tap into STDOUT.  Any way to keep the cmd.exe window open and show the STDIN or STDOUT in the cmd.exe window?

ahha

#AutoIt3Wrapper_run_debug_mode=Y

#include <Constants.au3>

example()
MsgBox($MB_SYSTEMMODAL, "Info", "Paused.")

Func example()
    Local $iPid = Run(@ComSpec, "", @SW_MAXIMIZE, $STDIN_CHILD)
    StdinWrite($iPid, "1234")
EndFunc
Link to comment
Share on other sites

1 hour ago, ahha said:

It looks like there is no way to keep the cmd.exe window open and show the STDIN.

@ahha

I guess it depends on what you are trying to accomplish.  If you just want to see the commands getting executed then you could do something like what's below.  If you actually need to capture the output, then there are better ways to do it.

Opt('WinTitleMatchMode', -2)

example()

Func example()
    Const $WINTITLE = "Test Window"
    Local $hWnd

    ;Launch CMD and get handle to window
    Run(@ComSpec & ' /c start "' & $WINTITLE & '" cmd.exe')
    $hWnd = WinWait($WINTITLE, "", 5)
    If Not $hWnd Then Exit -1

    ;Send commands
    WinActivate($hWnd)
    Sleep(1000)
    Send("CD \{ENTER}")
    Sleep(1000)
    Send("1234{ENTER}")
EndFunc

 

Edited by TheXman
Link to comment
Share on other sites

TheXman,

I was trying to understand how STDIN worked.  I actually want to issue commands via STDIN and read the output via STDOUT for diskpart.exe.  However, since diskpart.exe can really mess up your system I was trying to learn it on cmd.exe.  I'm stuck at trying to read the "DISKPART>" prompt in the program below.  I don't seem to get it via STDOUT.  I can copy the window to the clipboard and find it, but that's really a kludge.

ahha

#AutoIt3Wrapper_run_debug_mode=Y    ;use this to debug in console window <--- LOOK

#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>

Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase

$sWinTitle = "diskpart.exe"
$sProgram = "diskpart.exe"

$iPID = Run(@ComSpec & " /c " & $sProgram, @SystemDir, @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))

If $iPID = 0 Then
    MsgBox(0, "ERROR", "Failed to start: '" & $sProgram & "'")
    Exit
Else
    MsgBox(0, "Info", "$iPID = '" & $iPID & "'" & @CRLF & _
    "Click on User Account Control (UAC) to allow program to run - it may be winking in the taskbar.  Click on OK in this window, then Yes on the UAC.")
EndIf

WinWait($sWinTitle)
WinActivate($sWinTitle)
;need to wait for DISKPART> prompt - which can take some time as disks spin up
;will need to look at stdout

$sOutput = ""
While 1
    $sOutput &= StdoutRead($iPID)
    If @error Then ; Exit the loop if the process closes or StdoutRead returns an error.
        MsgBox($MB_SYSTEMMODAL, "ERROR", "StdoutRead returned an EOF.  We will exit loop.")
        ExitLoop
    EndIf
    MsgBox($MB_SYSTEMMODAL, "Stdout Read:", "$sOutput = '" & $sOutput & "'")
WEnd


MsgBox($MB_SYSTEMMODAL, "Exit", "About to exit program.")

Exit

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...