Jump to content

StdoutRead() can't find text in cmd console?


Blue0
 Share

Recommended Posts

Hi,

So I'm trying to make a script that runs a bat file, reads the console and does nothing unless it finds a word I define. I just can't get it to find the word. 😞

😦 Tried searching but didn't find out why this isn't working.

Also how do I make it so that the console still shows up on the screen? 🤨

#include <Constants.au3>

#AutoIt3Wrapper_Change2CUI=y

Global $ResponseText
Global $iPID
Global $CanWeExit = False
Global $xFilter = "restart"


Func _ReadConsole()
    $iPID = WinGetProcess("C:\Windows\system32\cmd.exe")
    While 1
        $ResponseText &= StdoutRead($iPID)
        If @error Then ExitLoop
    Wend
    If StringInStr($ResponseText, $xFilter) Then
        WinActivate("C:\Windows\system32\cmd.exe")
        Send("n")
        WinWaitClose("C:\Windows\system32\cmd.exe")
        $CanWeExit = True
    EndIf
EndFunc


Run(@DesktopDir & "\test.bat", "", @SW_SHOW, $STDOUT_CHILD)
WinWait("C:\Windows\system32\cmd.exe")
While 2
WinWaitClose("C:\Windows\system32\cmd.exe", "", 1)
If Not WinExists("C:\Windows\system32\cmd.exe") Then
    ExitLoop
EndIf
If WinExists("C:\Windows\system32\cmd.exe") Then
    Call("_ReadConsole")
EndIf
If $CanWeExit = True Then
    ExitLoop
EndIf
WEnd

This is in the bat file (EDIT3: This is just an example bat I made fast to get the word 'restart' in cmd console and not the actual bat I want to run)

@echo off
echo restart bat to test restart word search
echo would you like to restart
echo press y to restart
echo press n to not restart
pause

 

Edit: My goal isn't restarting the computer, but to press a key if the script finds my defined word in the console and does nothing if it doesn't.

Edited by Blue0
Link to comment
Share on other sites

Link to comment
Share on other sites

Because I need to run the bat.. the real bat I want to run installs stuff.. asks for restart (10% of the time). I want to do other stuff after running the bat before I restart. Can't do other stuff before pressing 'n' because cmd doesn't close before that and windows says other install is already in progress if I try to run another bat that also installs stuff. ☺️

Edited by Blue0
Phrasing better
Link to comment
Share on other sites

1 hour ago, Blue0 said:

Also how do I make it so that the console still shows up on the screen? 🤨

I think you're talking about executing via the command line. If so, include this at the top of your script:

#AutoIt3Wrapper_Change2CUI=y

Also, take a look at the Documentation, especially RunWait.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

12 minutes ago, seadoggie01 said:

I think you're talking about executing via the command line. If so, include this at the top of your script:

#AutoIt3Wrapper_Change2CUI=y

Also, take a look at the Documentation, especially RunWait.

Just tried putting #AutoIt3Wrapper_Change2CUI=y to the top of the script but still didn't find the word 'restart' in the console.

RunWait waits until it gets error code or the ran thing closes, right? If cmd ask user input before continuing the bat script, RunWait will just wait, right? So using WinWait and setting the timeout it will continue my script and check if it can find the word 'restart' and go back to waiting until WinWait gets timeout again. Or am I totally off the tracks?

Edited by Blue0
Link to comment
Share on other sites

Why using a .bat file and not using AutoIt in the first place?

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

2 minutes ago, jchd said:

Why using a .bat file and not using AutoIt in the first place?

I'm not the one who made the bat file. I'm just using it to install the program I wan't. 

It doesn't always ask if I wan't to restart or not. Only like 2/10 times it asks for restart. So I need to make it press 'N' so that it doesn't restart before all the stuff I want to do is done before that.

Edited by Blue0
Link to comment
Share on other sites

Make your life simpler and use AutoIt for that.  Just my $0.02

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

41 minutes ago, jchd said:

Make your life simpler and use AutoIt for that.  Just my $0.02

The bat runs msi file with some commads. Also it's updated frequently so instead of me having to check if there's a new msi file, figure out the commands (if they need changing or not) I can just run the premade bat.

Edited by Blue0
Link to comment
Share on other sites

@Blue0 AFAIK, console window (cmd.exe - to be specific) generates output using GDI (it's kinda graphic generating tool).

So what you see running in the cmd.exe window (text, for example) is actually generated graphic. That's the reason why AutoIT Window Info, WinSpy or other tools can not read console command's text.

For your issue, StdoutRead just read from STDOUT stream, so you need to modify the .bat to pipe your desired information to STDOUT.

Link to comment
Share on other sites

Gripe: So you're trying to run a broken batch file with AutoIt and execute a second command in case the batch file doesn't execute it? Do you see the irony here?

Anyways, try something more like this:

; Run your batch
; Wait for it to quit
ProcessWaitClose() ;<-- Look at the this function
; Get ALL the output from the process
; If the output contains your special word
    ; Do other stuff

Also, ignore my comment about #AutoIt3Wrapper_Change2CUI ... that's for getting ConsoleWrite() to output to the command line.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

2 hours ago, LukeLe said:

@Blue0 AFAIK, console window (cmd.exe - to be specific) generates output using GDI (it's kinda graphic generating tool).

So what you see running in the cmd.exe window (text, for example) is actually generated graphic. That's the reason why AutoIT Window Info, WinSpy or other tools can not read console command's text.

For your issue, StdoutRead just read from STDOUT stream, so you need to modify the .bat to pipe your desired information to STDOUT.

So there's no way of reading the content of cmd.exe window without changing the bat? I can't change the bat and the one who makes them probably won't change it.. Have to just use timeout with ridiculous wait time, see if the cmd window still exists and send the key.. ☹️

 

2 hours ago, seadoggie01 said:

Gripe: So you're trying to run a broken batch file with AutoIt and execute a second command in case the batch file doesn't execute it? Do you see the irony here?

Anyways, try something more like this:

; Run your batch
; Wait for it to quit
ProcessWaitClose() ;<-- Look at the this function
; Get ALL the output from the process
; If the output contains your special word
    ; Do other stuff

Also, ignore my comment about #AutoIt3Wrapper_Change2CUI ... that's for getting ConsoleWrite() to output to the command line.

I don't think it's broken bat.. It just sometimes installs something (maybe, not sure why) so that the bat script requests a restart to finish the installation.

Looked up the ProcessWaitClose. Isn't that basically the same thing as the WinWaitClose? How do I get the output from it?

Edited by Blue0
Link to comment
Share on other sites

@Blue0 Please check if this is what you're trying to achieve:

Run this:

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

$iPID = Run(@ComSpec & " /C " & @DesktopDir & "\Test.bat", @DesktopDir, @SW_HIDE, $STDERR_MERGED)
$sTmp = ""
While ProcessExists($iPID)
    $sTmp = StdoutRead($iPID)
    If StringLen($sTmp) > 0 Then ConsoleWrite($sTmp)
WEnd

Test.bat's content:

@echo off
echo restart bat to test restart word search
echo would you like to restart
echo press y to restart
echo press n to not restart
pause

This is the output running on my computer:

+>13:19:48 Starting AutoIt3Wrapper v.19.102.1901.0 SciTE v.4.1.2.0   Keyboard:00000409  OS:WIN_7/Service Pack 1  CPU:X64 OS:X64  Environment(Language:0409)  CodePage:  utf8.auto.check:
+>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
restart bat to test restart word search
would you like to restart
press y to restart
press n to not restart
Press any key to continue . . . 
+>13:19:48 AutoIt3.exe ended.rc:0
+>13:19:48 AutoIt3Wrapper Finished.
Process exited with code 0

 

Link to comment
Share on other sites

9 hours ago, jchd said:

Make your life simpler and use AutoIt for that.  Just my $0.02

@Blue0 :

In your place I would really try to follow the advice of @jchd (if possible). Most installers can be controlled via command line parameters, such as /SILENT , /NORESTART and so on. This is more reliable than processing CMD console streams.

9 hours ago, Blue0 said:

The bat runs msi file with some commands.

Here e.g. a list of command line arguments for MSIEXEC :

https://www.robvanderwoude.com/msiexec.php

Spoiler

Windows Installer (MSIEXEC)

Documented command line arguments

Type MSIEXEC /? and you'll get the following on-screen help:


	Windows ® Installer. V 5.0.7601.17514
	
	msiexec /Option <Required Parameter> [Optional Parameter]
	
	Install Options
		</package | /i> <Product.msi>
			Installs or configures a product
		/a <Product.msi>
			Administrative install - Installs a product on the network
		/j<u|m> <Product.msi> [/t <Transform List>] [/g <Language ID>]
			Advertises a product - m to all users, u to current user
		</uninstall | /x> <Product.msi | ProductCode>
			Uninstalls the product
	
	Display Options
		/quiet
			Quiet mode, no user interaction
		/passive
			Unattended mode - progress bar only
		/q[n|b|r|f]
			Sets user interface level
			n - No UI
			b - Basic UI
			r - Reduced UI
			f - Full UI (default)
		/help
			Help information
	
	Restart Options
		/norestart
			Do not restart after the installation is complete
		/promptrestart
			Prompts the user for restart if necessary
		/forcerestart
			Always restart the computer after installation
	
	Logging Options
		/l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>
			i - Status messages
			w - Nonfatal warnings
			e - All error messages
			a - Start up of actions
			r - Action-specific records
			u - User requests
			c - Initial UI parameters
			m - Out-of-memory or fatal exit information
			o - Out-of-disk-space messages
			p - Terminal properties
			v - Verbose output
			x - Extra debugging information
			+ - Append to existing log file
			! - Flush each line to the log
			* - Log all information, except for v and x options
		/log <LogFile>
			Equivalent of /l* <LogFile>
	
	Update Options
		/update <Update1.msp>[;Update2.msp]
			Applies update(s)
		/uninstall <PatchCodeGuid>[;Update2.msp] /package <Product.msi | ProductCode>
			Remove update(s) for a product
	
	Repair Options
		/f[p|e|c|m|s|o|d|a|u|v] <Product.msi | ProductCode>
			Repairs a product
			p - only if file is missing
			o - if file is missing or an older version is installed (default)
			e - if file is missing or an equal or older version is installed
			d - if file is missing or a different version is installed
			c - if file is missing or checksum does not match the calculated value
			a - forces all files to be reinstalled
			u - all required user-specific registry entries (default)
			m - all required computer-specific registry entries (default)
			s - all existing shortcuts (default)
			v - runs from source and recaches local package
	
	Setting Public Properties
		[PROPERTY=PropertyValue]
	
	Consult the Windows ® Installer SDK for additional documentation on the
	command line syntax.
	
	Copyright © Microsoft Corporation. All rights reserved.
	Portions of this software are based in part on the work of the Independent JPEG Group.

Undocumented (1) command line arguments

My colleague Adriaan Westra taught me the trick to suppress reboots when installing .MSI files from the command line (better believe me, /norestart rarely does what its name suggests):


MSIEXEC /i myfile.msi /qn REBOOT=ReallySuppress

This made me curious if there are more unknown arguments, so I started experimenting.
Try for yourself, type:


STRINGS MSIEXEC.EXE | FINDSTR /R /C:"[A-Z][A-Z]\="

and you'll find the following "undocumented" command line arguments (called "Public Properties" in MSIEXEC's on-screen help) and their default values:


REMOVE=ALL
ACTION=ADMIN
REINSTALL=ALL
REBOOTPROMPT=""
REBOOT=Force
REBOOT=ReallySuppress
MSIPATCHREMOVE=
PATCH=
Note: (1) Actually these command line arguments are documented, but they are not mentioned in the on-screen help displayed when typing MSIEXEC /?.

 

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to comment
Share on other sites

Hello,

this should help you out of your Problem:

 

#include <AutoItConstants.au3>

$Bat="C:\temp\test.bat"

$hBat=FileOpen($Bat,2+8)
FileWriteLine($hBat,'@echo off')
FileWriteLine($hBat,'echo this is the first echo line')
FileWriteLine($hBat,':RESTART')
FileWriteLine($hBat,'echo this is the second line')
FileWriteLine($hBat,'choice /c YN /m "do you want to restart?"')
FileWriteLine($hBat,'if errorlevel 2 goto EXIT')
FileWriteLine($hBat,'if errorlevel 1 goto RESTART')
FileWriteLine($hBat,':EXIT')
FileWriteLine($hBat,'echo this is the END...')
FileClose($hBat)


$pid=Run(@ComSpec & ' /C "' &  $Bat & '"',@TempDir, @SW_HIDE, $STDIN_CHILD + $STDERR_MERGED)

$StrOutput=""
$StrMatch="restart"
$Found=0
ToolTip($StrOutput,100,100,$Found)
while ProcessExists($pid)
    $StrOutput &= StdoutRead($pid)
    ToolTip($StrOutput,100,100,$Found)
    if StringInStr($StrOutput,$StrMatch) Then
        if $Found > 2 Then
            $Char="n"
        Else
            $Char="y"
        EndIf
        $Found+=1
        StdinWrite($pid,$Char)
    EndIf
    Sleep(100) ; waiting for BAT file to vanish
WEnd

MsgBox(0,"Process vanished","number of matches found: " & $Found & @CRLF & $StrOutput)

Explanation:

  1. You have to add $STDIN_CHILD for your run command
  2. You have to use StdinWrite(), not "send()" to write to the console of your BAT file.

 

cu, Rudi.

PS: I guess that BAT file is maintained by some other Person or department, and so it's a "take it or leave it Option" to you.
Nevertheless it's worth a try, that +YOU+ encourage this other Person or dept to natively use autoit for These Tasks, as several other answers here mentioned before.

Edited by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

@Blue0 I am able to send data to the cmd but I can not retrieve it. (The majority of this code was found on the Autoit forms) 

Func test3()
    AutoItSetOption("WinTitleMatchMode", 2)
    Run("cmd")
    WinWaitActive("cmd")

    For $i = 65 To 90
        WinActivate("cmd")
        WinWaitActive("cmd")
        ControlSend("cmd", "", "", Chr($i))

        ;MsgBox(0, "Chr(" & $i & ")", Chr($i), 2)

        Local $sText3 = ControlGetText("cmd", "command", "")

        ConsoleWrite(@CRLF & @CRLF & "Test3: " & $sText3 & @CRLF & @CRLF)
    Next
EndFunc

This data to the cmd and can execute it but I am having a hard time correctly retrieving that data and displaying it.

AKA: I can send it to the cmd console. I can not get from the cmd console.

(Sends the Alphabet)   

Edited by nooneclose
Cleaner code
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...