Jump to content
Sign in to follow this  
Zhelkus

StdoutRead() doesn't output anything until the process finishes

Recommended Posts

Zhelkus

I have a script where I want to make a progress bar according to the program's completion of a certain task. For this matter I'm using 7zip. The last characters for almost each line is the percentage of the progress of the archive's creation. However, when I use StdoutRead() the stream returns blank until the program finishes. The same happens for any other command line program I use.

I even created a dummy/test script to see if I could tweak something like peeking at the stream but it won't reveal anything... Here's what I've been doing:

#include <GUIConstants.au3>
#include <GuiEdit.au3>

GUICreate("Firefox backup", 600, 700)
$edit1 = GUICtrlCreateEdit("", -1, -1, 600, 700)
GUISetState(@SW_SHOW)

$program = "7z.exe"
$parameter = " a -t7z ""C:\Users\" & @UserName & "\Programs\test.7z"" ""C:\Users\" & @UserName & "\Music\Mike Oldfield - Moonlight Shadow (12' Extended Version).mp3"""; just a file big enough and slow enough to compress and observe StdoutRead() working

$7zstdout = Run(@ComSpec & " /k " & $program & $parameter, "C:\Program Files\7-Zip", @SW_SHOW, 8)
If @error Then
    MsgBox(16, "Error", "something happened with the process")
    Exit
EndIf

While 1
    $line = StdoutRead($7zstdout, 0)
    If @error Then ExitLoop
    
    _GUICtrlEdit_AppendText($edit1, $line)
    Sleep(25)
WEnd

_GUICtrlEdit_AppendText($edit1, @CRLF & "Finished.")

While 1
    $msg = GUIGetMsg()

    If $msg == $GUI_EVENT_CLOSE Then Exit
WEnd

I've searched the forum and found people having similar problems (if not the same) but I can't make out how they solved it... I'm too n00bish :)

Share this post


Link to post
Share on other sites
martin

I have a script where I want to make a progress bar according to the program's completion of a certain task. For this matter I'm using 7zip. The last characters for almost each line is the percentage of the progress of the archive's creation. However, when I use StdoutRead() the stream returns blank until the program finishes. The same happens for any other command line program I use.

I even created a dummy/test script to see if I could tweak something like peeking at the stream but it won't reveal anything... Here's what I've been doing:

#include <GUIConstants.au3>
#include <GuiEdit.au3>

GUICreate("Firefox backup", 600, 700)
$edit1 = GUICtrlCreateEdit("", -1, -1, 600, 700)
GUISetState(@SW_SHOW)

$program = "7z.exe"
$parameter = " a -t7z ""C:\Users\" & @UserName & "\Programs\test.7z"" ""C:\Users\" & @UserName & "\Music\Mike Oldfield - Moonlight Shadow (12' Extended Version).mp3"""; just a file big enough and slow enough to compress and observe StdoutRead() working

$7zstdout = Run(@ComSpec & " /k " & $program & $parameter, "C:\Program Files\7-Zip", @SW_SHOW, 8)
If @error Then
    MsgBox(16, "Error", "something happened with the process")
    Exit
EndIf

While 1
    $line = StdoutRead($7zstdout, 0)
    If @error Then ExitLoop
    
    _GUICtrlEdit_AppendText($edit1, $line)
    Sleep(25)
WEnd

_GUICtrlEdit_AppendText($edit1, @CRLF & "Finished.")

While 1
    $msg = GUIGetMsg()

    If $msg == $GUI_EVENT_CLOSE Then Exit
WEnd

I've searched the forum and found people having similar problems (if not the same) but I can't make out how they solved it... I'm too n00bish :)

Have a look at the help for StdoutRead and the example. I think that is what you need.

EDIT:

Maybe this example will help (not like the help I referred to above)

#include <Constants.au3>

While 1
    $data = ''
    $instr = InputBox("DOS commander", "next command")
    If $instr = '' Then Exit

    Local $foo = Run("cmd.exe", @SystemDir, @SW_HIDE, 9);$STDIN_CHILD + $STDOUT_CHILD)cmd.exe
    StdinWrite($foo, $instr & @CRLF);& "cat" & @CRLF & "bat" & @CRLF)
; Calling with no 2nd arg closes stream
    StdinWrite($foo)

; Read from child's STDOUT and show
    Local $data
    While True
        $data &= StdoutRead($foo)
        If @error Then ExitLoop
        Sleep(25)
    WEnd
    MsgBox(0, "DOS output", $data)
WEnd
Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Zhelkus

I tried to follow the help file's script as it was laid out but I don't understand where I'm wrong. In your example above you have $data store all the outputs form the stream but you set to display it at the end. What I want is to read the stream as the program is running.

Now, like I said, I'm just a noob at this so if you solved it for me I may have overlooked it :) That's why I'd rather ask you to explain it to me if possible, please. Thanks for the reply btw.

Share this post


Link to post
Share on other sites
martin

I tried to follow the help file's script as it was laid out but I don't understand where I'm wrong. In your example above you have $data store all the outputs form the stream but you set to display it at the end. What I want is to read the stream as the program is running.

Now, like I said, I'm just a noob at this so if you solved it for me I may have overlooked it :) That's why I'd rather ask you to explain it to me if possible, please. Thanks for the reply btw.

I modified my script to be like yours. Can you try this?

#include <GUIConstants.au3>
#include <GuiEdit.au3>

GUICreate("Firefox backup", 600, 700)
$edit1 = GUICtrlCreateEdit("", -1, -1, 600, 700)
GUISetState(@SW_SHOW)

$program = "7z.exe"

$parameter = " a -t7z ""C:\Users\" & @UserName & "\Programs\test.7z"" ""C:\Users\" & @UserName & "\Music\Mike Oldfield - Moonlight Shadow (12' Extended Version).mp3"""; just a file big enough and slow enough to compress and observe StdoutRead() working

Local $7zstdout = Run("cmd.exe", @SystemDir, @SW_HIDE, 9)
StdinWrite($7zstdout, $program & $parameter & @CRLF)
StdinWrite($7zstdout)

 Local $line
    While True
        $line = StdoutRead($7zstdout)
         If @error Then ExitLoop
         _GUICtrlEdit_AppendText($edit1, $line)
        Sleep(25)
    WEnd


While 1
    $line = StdoutRead($7zstdout, 0)
    If @error Then ExitLoop
   
    _GUICtrlEdit_AppendText($edit1, $line)
    Sleep(25)
WEnd

_GUICtrlEdit_AppendText($edit1, @CRLF & "Finished.")

while 1
    if GUIGetMsg() = -3 then exit
WEnd

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
rasim

Zhelkus

Works fine for me:

#include <GuiConstantsEx.au3>
#include <Constants.au3>

$hGUI = GUICreate("Test", 300, 200)

$cEdit = GUICtrlCreateEdit("", 10, 10, 280, 140)

$cButtonTest = GUICtrlCreateButton("Test", 11, 166, 75, 23)

GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cButtonTest
            _ArciveTest("d:\Info\AutoIt\autoit_threads_archive.7z")
    EndSwitch
WEnd

Func _ArciveTest($sArchive)
    Local $iPID, $sStdOut
    
    $iPID = Run(@ComSpec & ' /c 7z.exe t "' & $sArchive & '"', @SystemDir, @SW_HIDE, BitOR($STDOUT_CHILD, $STDERR_CHILD))
    
    While 1
        $sStdOut = StdoutRead($iPID)
        If @error Then ExitLoop
        If Not $sStdOut = "" Then GUICtrlSetData($cEdit, $sStdOut & @CRLF, 1)
        Sleep(1)
    WEnd
EndFunc

:)

P.S.

For easy and best results use the 7Zip UDF from my signature :o

Share this post


Link to post
Share on other sites
Zhelkus

Thanks for the replies guys. I'm almost convinced that there's something wrong my understanding of how StdoutRead() works... because it's still not working on my PC (could Vista be the reason? lol). I've tried both code suggestions and they all work the same.

#include <GUIConstants.au3>
#include <GuiEdit.au3>

GUICreate("Firefox backup", 600, 700)
$edit1 = GUICtrlCreateEdit("", -1, -1, 600, 700)
GUISetState(@SW_SHOW)

$program = "7z.exe"
$parameter = " a -t7z ""C:\Users\" & @UserName & "\Programs\test.7z"" ""C:\Users\" & @UserName & "\Music\Mike Oldfield - Moonlight Shadow (12' Extended Version).mp3"""; just a file big enough and slow enough to compress and observe StdoutRead() working

;~ Local $7zstdout = Run("cmd.exe", "C:\Program Files\7-zip", @SW_HIDE, BitOR(1,8))
Local $7zstdout = Run(@ComSpec & " /c 7z.exe " & $parameter, "C:\Program Files\7-zip", @SW_HIDE, BitOR(1,8))
;~ StdinWrite($7zstdout, $program & $parameter & @CRLF)
;~ StdinWrite($7zstdout)

Local $line
Local $line2 = ""
While True
    $line = StdoutRead($7zstdout, 1)
    If @error Then ExitLoop
    
;~  _GUICtrlEdit_AppendText($edit1, $line & @CRLF)
    If Not $line = "" And $line <> $line2 Then GUICtrlSetData($edit1, $line & @CRLF,1)
    $line2 = $line
    Sleep(25)
WEnd

_GUICtrlEdit_AppendText($edit1, @CRLF & "Finished.")

While 1
    if GUIGetMsg() == -3 then exit
WEnd

I believed that StdoutRead() would allow me to read the messages output in the command line by a process while it was running. Say, recreate the the percentage of an image conversion in real-time in an edit control, or watch the files being added to an archive in real-time, which is this case, etc. And thanks for the 7zip UDF, rasim, but what I want to try to do now is understand how this works and use it for other small programs I have floating around that require manual input. The manual explains it so easy and clean... until it covers this part... self-teaching suddenly starts to get harder... *sob*.

So far, every try throws out the entire output in a single turn once the program has finished and closes. Peeking at the output only displays the same info over and over again repeatedly until the character limit for the edit control is reached. That's why I added the "$line2 <> $line" to the If.

I honestly thought I was getting the hang of this until I stumbled here... oh the sorrow... *sniff*.

Share this post


Link to post
Share on other sites
jennico

there is a really wonderful script by valik. at least it is able to read the percentage from the 7zip window.

it is hard to find, so i link it here.

cheers j.

edit:

no need to compile it. it can be run as .au3 or integrated in your own script with modifications in the main function.

Edited by jennico

Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

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  

×