Sign in to follow this  
Followers 0
gerwim

Read last line CMD

19 posts in this topic

Hi there,

So I'm new to AutoIt, kinda and I want to read the last line of a CMD file. And when it is a specific string, I want it to run a .bat file.

So:

1. The .bat file is opened

2. When it crashes (thus giving a specific string in CMD) restart the .bat file.

Obviously the first item is easy, and the second one I know i can use StdOutRead but I'm not sure how to read the last line.

Thanks in advance!

Gerwim

Share this post


Link to post
Share on other sites



How do you know when the last line of your CMD has been displayed (a special string in it, the DOS window is closed ...)?

Is the last line different if the CMD crashes or runs successfully?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

The easiest way is probably to not split the string at all, but just use StringRegexp, or StringInStr to check if a given substring exists.

With StringRegExp you can even specify that you only want to return true if the search string is at the end of the returned string.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Modified example from AutoIt Help:

#include <Constants.au3>

; instead "dir" use your bat-file
Local $foo = Run(@ComSpec & " /c dir ", @SystemDir, @SW_HIDE, $STDOUT_CHILD)
Local $sOut = ''
While 1
    $line = StdoutRead($foo)
    If @error Then ExitLoop
    $sOut &= $line
;~     MsgBox(0, "STDOUT read:", $line)
Wend
ConsoleWrite('last line: ' & $line & @CRLF) ; may be empty - so use "ALL" and see last non-empty
ConsoleWrite('ALL' & @CRLF & $sOut & @CRLF)
Edited by BugFix

Best Regards BugFix  

Share this post


Link to post
Share on other sites

@BugFix:

As far as I know StdOutRead doesn't read the output one line at the time. It just takes any data available, which could be a wall of text, or a single character. So in a tight loop $line will have a few characters at best, not the entire last line.

Another probem is that you're only displaying $line after StdOutRead has returned an error, in which case I assume $line will be blank.

Share this post


Link to post
Share on other sites

Modified example from AutoIt Help:

#include <Constants.au3>

; instead "dir" use your bat-file
Local $foo = Run(@ComSpec & " /c dir ", @SystemDir, @SW_HIDE, $STDOUT_CHILD)
Local $sOut = ''
While 1
    $line = StdoutRead($foo)
    If @error Then ExitLoop
    $sOut &= $line
;~     MsgBox(0, "STDOUT read:", $line)
Wend
ConsoleWrite('last line: ' & $line & @CRLF) ; may be empty - so use "ALL" and see last non-empty
ConsoleWrite('ALL' & @CRLF & $sOut & @CRLF)

Thanks, this is what I needed :-)

Share this post


Link to post
Share on other sites

Modified example from AutoIt Help:

#include <Constants.au3>

; instead "dir" use your bat-file
Local $foo = Run(@ComSpec & " /c dir ", @SystemDir, @SW_HIDE, $STDOUT_CHILD)
Local $sOut = ''
While 1
    $line = StdoutRead($foo)
    If @error Then ExitLoop
    $sOut &= $line
;~     MsgBox(0, "STDOUT read:", $line)
Wend
ConsoleWrite('last line: ' & $line & @CRLF) ; may be empty - so use "ALL" and see last non-empty
ConsoleWrite('ALL' & @CRLF & $sOut & @CRLF)

It's not working correctly for me though:

Func Start()
    Global $PID = Run("server_nogui.bat", "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    GUICtrlSetState($BTN_Restart, $GUI_ENABLE)
    GUICtrlSetState($BTN_Stop, $GUI_ENABLE)
    GUICtrlSetState($BTN_Start, $GUI_DISABLE)
    GUICtrlSetData($status, "Running")
    GuiCtrlSetData($CMDOutput, "Server is starting...")
    
    Local $sOut = ''
    While 1
        $line = StdoutRead($PID)
        If @error Then ExitLoop
        $sOut &= $line
    ;MsgBox(0, "STDOUT read:", $line)
    _GUICtrlEdit_InsertText($CMDOutput, & @CRLF&$line , -1)
    Wend
    
EndFunc

I get this error message:

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "D:\bin\server.au3"

D:\bin\server.au3 (64) : ==> Error in expression.:

_GUICtrlEdit_InsertText($CMDOutput, & @CRLF&$line , -1)

_GUICtrlEdit_InsertText($CMDOutput, ^ ERROR

>Exit code: 1 Time: 1.213

Anyone knows whats going on?

Cheers

Share this post


Link to post
Share on other sites

Change

_GUICtrlEdit_InsertText($CMDOutput, & @CRLF&$line , -1)

to

_GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Hmm, its still not working.

I added a msgbox out of the loop and it pops up, which means it exits the loop.

It even exits the "error" loop, thus somehow he cant read the PID?

My code:

Func Start()
    Global $PID = Run("server_nogui.bat", "", $STDOUT_CHILD)
    
    GUICtrlSetState($BTN_Restart, $GUI_ENABLE)
    GUICtrlSetState($BTN_Stop, $GUI_ENABLE)
    GUICtrlSetState($BTN_Start, $GUI_DISABLE)
    GUICtrlSetData($status, "Running")
    GuiCtrlSetData($CMDOutput, "Server is starting...")
    
    Local $sOut = ''
    While 1
        $line = StdoutRead($PID)
        If @error Then ExitLoop
        $sOut &= $line
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

    While 1
        $line = StderrRead($PID)
        If @error Then ExitLoop
        MsgBox(0, "STDERR read:", $line)
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

MsgBox(0, "Debug", "Exiting...")

    
    
EndFunc
Edited by gerwim

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Hmm, its still not working.

"Not working" means: You still get an error message? No text appears with MsgBox? No text appears in the Edit Control? Something else? Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

It means that I just get the message "Exiting..." and nothing shows up in my edit control. (Except "Server starting").

Edit: for clarification: I want the CMD output to be "redirected" into the edit control.

Edited by gerwim

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Could you insert a ConsoleWrite or MsgBox in the loop where you read STDOUT? So we can see if any output is gathered by your script or if the problem is with _GUICtrlEdit_InsertText.

EDIT: Your run command is incomplete. $STDOUT_CHILD has to bee the 4th parameter. In you script it's parameter 3. So please change

Global $PID = Run("server_nogui.bat", "", $STDOUT_CHILD)
to

Global $PID = Run("server_nogui.bat", "", "", $STDOUT_CHILD)
Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Func Start()
    Global $PID = Run("server_nogui.bat", "", $STDOUT_CHILD)
    
    GUICtrlSetState($BTN_Restart, $GUI_ENABLE)
    GUICtrlSetState($BTN_Stop, $GUI_ENABLE)
    GUICtrlSetState($BTN_Start, $GUI_DISABLE)
    GUICtrlSetData($status, "Running")
    GuiCtrlSetData($CMDOutput, "Server is starting...")
    
    Local $sOut = ''
    While 1
        $line = StdoutRead($PID)
        MsgBox(0, "Msg", $line)
        If @error Then ExitLoop
        $sOut &= $line
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

    While 1
        $line = StderrRead($PID)
        If @error Then ExitLoop
        MsgBox(0, "STDERR read:", $line)
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

MsgBox(0, "Debug", "Exiting...")

    
    
EndFunc

This will bring up unlimited MsgBoxes with no data in them. I see the edit control being filled up to with empty lines (I know since I see the scrollbar getting smaller).

Fyi: I can't close the PID aswell, so I used WinKill (not sure if this has anything to do with it tho)

Edited by gerwim

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I edited my previous post.

The error is with the number of parameters you pass to the run command!

Edited by water

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

Thanks! It works now (half tho ;))

I can see some text popping up in the edit control, but it get's filled with white space right after. I think it's due to the while loop.

I only want to update the edit control when there's a new message in the cmd window. How can this be done? My full script (excluding GUI):

Opt("WinTitleMatchMode", 2)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Stop()
            Exit
        Case $BTN_Start
            Start()
        Case $BTN_Restart
            Restart()
        Case $BTN_Stop
            Stop()

    EndSwitch
WEnd

Func Start()
    Global $PID = Run("server_nogui.bat", "", "", $STDOUT_CHILD)
    
    GUICtrlSetState($BTN_Restart, $GUI_ENABLE)
    GUICtrlSetState($BTN_Stop, $GUI_ENABLE)
    GUICtrlSetState($BTN_Start, $GUI_DISABLE)
    GUICtrlSetData($status, "Running")
    GuiCtrlSetData($CMDOutput, "Server is starting...")
    
    Local $sOut = ''
    While 1
        $line = StdoutRead($PID)
        ;MsgBox(0, "Msg", $line)
        If @error Then ExitLoop
        $sOut &= $line
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

    While 1
        $line = StderrRead($PID)
        If @error Then ExitLoop
        MsgBox(0, "STDERR read:", $line)
        _GUICtrlEdit_InsertText($CMDOutput, @CRLF & $line , -1)
    Wend

MsgBox(0, "Debug", "Exiting...")

    
    
EndFunc

Func Restart()
    ;Stop()
    ;Sleep(500)
    ;Start()
    CMD("save-all")
    
EndFunc

Func Stop()
    WinKill("32\cmd.exe")
    
    
    GUICtrlSetState($BTN_Restart, $GUI_DISABLE)
    GUICtrlSetState($BTN_Stop, $GUI_DISABLE)
    GUICtrlSetState($BTN_Start, $GUI_ENABLE)
    GUICtrlSetData($status, "Stopped")
    _GUICtrlEdit_InsertText($CMDOutput, & @CRLF"Server closing down..." , -1)
EndFunc

Func CMD($message)
    ControlSend("32\cmd.exe", "", "", $message &"{ENTER}")
EndFunc

Share this post


Link to post
Share on other sites

I have a test script that only does a "DIR" command in the bat file and I get a lot of empty lines as well.

So I changed the script to suppress empty lines:

Global $PID = Run("test.bat", "", "", 0x2)
While 1
 $line = StdoutRead($PID)
 If @error Then ExitLoop
 If $line <> "" Then ConsoleWrite($line & @CRLF)
Wend

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Alright, it's working now. Thanks!

Yet I have another error (i'm think this is related to the .bat file, but I like to know whether this is fixable or not).

The error in the bottem screen in scite:

>"C:\Program Files\AutoIt3\SciTE\..\autoit3.exe" /ErrorStdOut "D:\bin\server.au3"    
java.io.IOException: De ingang is ongeldig
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)
    at java.io.BufferedReader.fill(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at bn.run(bn.java:18)

Edit:

A Run() cmd with as opt-flag 0x10000 works, but then the output cannot be read.

Edited by gerwim

Share this post


Link to post
Share on other sites

After a bit experimenting with multiple flags, I just can't get it right. Flag 0x10000 works but then Java doesn't have the IO. Is there a way to fix / trick this?

Share this post


Link to post
Share on other sites

Anyone?

Share this post


Link to post
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
Sign in to follow this  
Followers 0