Jump to content
Sign in to follow this  
Lazycat

StdoutRead problem

Recommended Posts

I started playing with StdoutRead yesterday and faced with problem, where StdoutRead not read output, when text changes inline. For example, here is output of well known utility Secure Delete:

SDelete - Secure Delete v1.2
Copyright (C) 1999-2003 Mark Russinovich
Systems Internals - www.sysinternals.com

SDelete is set for 1 pass.
Cleaning free space on C:\: 0%

StdoutRead capture first screen, but not react on percent changes.

With some other programs this not capture even beginning, when program start working (UPX, console Vorbis encoders).

I can be wrong, but seems almost all those problem programs are not add new lines in output when working. Despite of this they are standard console apps, i.e. when running without commandline keys output captures just fine.

Any thoughs how to bypass this situation?

Here is test code:

#include <GuiConstants.au3>

GuiCreate("GUI")
$hEdit = GuiCtrlCreateEdit("", 5, 5, 300, 200)
GuiSetState()

;$PID = Run(@comspec & " /c dir c:", "", @SW_MINIMIZE, 2); Works fine
$PID = Run("sdelete.exe -z c:", "", @SW_MINIMIZE, 2); Output first screen, but not change later
;$PID = Run("upx.exe --best -k mplayerc.exe", "", @SW_MINIMIZE, 2); Not output anything

While 1
      If StdoutRead($PID, 0 , 1) Then
         GUICtrlSetData($hEdit, StdoutRead($PID), 1)
      ElseIf @error = -1 Then 
         Sleep(3000)
         Exit
      Endif
   $nMsg = GuiGetMsg()
   Select
      Case $nMsg = $GUI_EVENT_CLOSE
         ProcessClose($PID)
         Exit
   EndSelect
WEnd

Sorry if this was mentioned somewhere, but I not found corresponding info :(

Share this post


Link to post
Share on other sites

Its possible to write text to a console window without actually using the stdout handle. I would assume applications performing "inline" text operations in this manner do not use stdout but rather use the OS's underlying operations for writing to a console window.

Share this post


Link to post
Share on other sites

This is what I receive from upx, with your code.

$PID = Run("upx.exe -d c:\test.exe", "", @SW_MINIMIZE, 2)

Ultimate Packer for eXecutables
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
UPX 1.25w       Markus F.X.J. Oberhumer & Laszlo Molnar     Jun 29th 2004

        File size        Ratio    Format      Name
   --------------------   ------   -----------   -----------
    255579 <-   120411   47.11% win32/pe     test.exe

Unpacked 1 file.

Share this post


Link to post
Share on other sites

Valik

I think you right, thanks for explanation. And I hope that solution can be found. Probably Dave can say something encouraging :(

MHZ

Yes, it capture final screen, but infortunately not take intermediate data, which I would like to capture for progress purposes.

Share this post


Link to post
Share on other sites

I remember my first thread. --> Read stdout and stderr in real time

(Std... thing was not available at this time)

For now i have no solution.

Maybe a kind of snapshot at specified intervals, stdoutchange or stderrchange is an idea :(

<{POST_SNAPBACK}>

Well, as I said before, the data isn't on stdout/stderr, its being written directly to the console's buffer. There are ways to read and write to the buffer directly. Looking up ReadConsoleOutput() on MSDN would be a good start, however, I suspect that in order to achieve this via AutoIt, it'll be pretty messy (Lots of Structure and DLL stuff).

Share this post


Link to post
Share on other sites

Thinking.

Still here, looking at the source of SDelete to see if he's using Win32 API or something lower-level to write the progress...

Edited by DaveF

Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines.

Share this post


Link to post
Share on other sites

OK, here's the output that I got from running your code on my Win XP Home PC with the 3.1.1.41 Beta, Lazycat:

SDelete - Secure Delete v1.4

Copyright © 1999-2005 Mark Russinovich

Sysinternals - www.sysinternals.com

SDelete is set for 1 pass.

Cleaning free space on A:\: 0%

Cleaning free space on A:\: 24%

Cleaning free space on A:\: 48%

Cleaning free space on A:\: 72%

Cleaning free space on A:\: 96%

Cleaning free space on A:\: 100%

Free space cleaned on A:\                                     

...that's an actual cut-and-paste from the edit box. Now, what it looked like in the edit box was this:

SDelete - Secure Delete v1.4

Copyright © 1999-2005 Mark Russinovich

Sysinternals - www.sysinternals.com

SDelete is set for 1 pass.

Cleaning free space on A:\: 0%Cleaning free space on A:\: 24%Cleaning free space on A:\: 48%Cleaning free space on A:\: 72%Cleaning free space on A:\: 96%Cleaning free space on A:\: 100%Free space cleaned on A:\                                     

...because the edit box didn't understand the CR-without-a-LF that was at the front of each string to send it back to the beginning of the line, overwriting the previous % completed message.

I tried creating the edit box with the default styles | $ES_OEMCONVERT, but it didn't change anything.

I was able to get what was supposed to be a running progress, but for me the output from SDelete doesn't get buffered right so everything but the initial 0% appears in one blurt at the end...

#include <GuiConstants.au3>

GuiCreate("GUI")
$hEdit = GuiCtrlCreateEdit("", 5, 5, 300, 200)
$hProgress = GUICtrlCreateProgress(5, 225, 300, 20)
GuiSetState()

;$PID = Run(@comspec & " /c dir c:", "", @SW_MINIMIZE, 2); Works fine
$PID = Run("sdelete.exe -z a:", "", @SW_MINIMIZE, 2); Output first screen, but not change later
;$PID = Run("upx.exe --best -k mplayerc.exe", "", @SW_MINIMIZE, 2); Not output anything

While 1
      $peek = StdoutRead($PID, -1 , 1)
      $bailout = @error
      If $peek Then
        If StringInStr($peek, "%") Then
          $read = StdoutRead($PID)
          $matches = StringRegExp($read, "(\d+)[%]", 3)
          If (Not @error) And (@extended) Then
            For $step = 0 To UBound($matches) - 1
              GUICtrlSetData($hProgress, Number($matches[$step]))
            Next
          EndIf
          GUICtrlSetData($hEdit, $read, 1)
        EndIf
      ElseIf $bailout = -1 Then 
         Sleep(9000)
         Exit
      Endif
   $nMsg = GuiGetMsg()
   Select
      Case $nMsg = $GUI_EVENT_CLOSE
         ProcessClose($PID)
         Exit
   EndSelect
WEnd

I didn't test if the results were better if one doesn't peek for data before reading it; it could be that you'd get more realistic progress that way, but the GUI message loop wouldn't be progressed while AutoIt was blocked...


Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines.

Share this post


Link to post
Share on other sites

I was able to get what was supposed to be a running progress, but for me the output from SDelete doesn't get buffered right so everything but the initial 0% appears in one blurt at the end...

Yes, and this is my problem... :(

I saw Sdelete source, but not find there any special console functions, just regular printf. No thoughts where the problem lay.

I didn't test if the results were better if one doesn't peek for data before reading it; it could be that you'd get more realistic progress that way, but the GUI message loop wouldn't be progressed while AutoIt was blocked...

I tried this scenario before starting thread. As you say, it just block loop until end.

Share this post


Link to post
Share on other sites

OK, here's the output that I got from running your code on my Win XP Home PC with the 3.1.1.41 Beta, Lazycat:

...that's an actual cut-and-paste from the edit box. Now, what it looked like in the edit box was this:

...because the edit box didn't understand the CR-without-a-LF that was at the front of each string to send it back to the beginning of the line, overwriting the previous % completed message.

I tried creating the edit box with the default styles | $ES_OEMCONVERT, but it didn't change anything.

I was able to get what was supposed to be a running progress, but for me the output from SDelete doesn't get buffered right so everything but the initial 0% appears in one blurt at the end...

#include <GuiConstants.au3>

GuiCreate("GUI")
$hEdit = GuiCtrlCreateEdit("", 5, 5, 300, 200)
$hProgress = GUICtrlCreateProgress(5, 225, 300, 20)
GuiSetState()

;$PID = Run(@comspec & " /c dir c:", "", @SW_MINIMIZE, 2); Works fine
$PID = Run("sdelete.exe -z a:", "", @SW_MINIMIZE, 2); Output first screen, but not change later
;$PID = Run("upx.exe --best -k mplayerc.exe", "", @SW_MINIMIZE, 2); Not output anything

While 1
      $peek = StdoutRead($PID, -1 , 1)
      $bailout = @error
      If $peek Then
        If StringInStr($peek, "%") Then
          $read = StdoutRead($PID)
          $matches = StringRegExp($read, "(\d+)[%]", 3)
          If (Not @error) And (@extended) Then
            For $step = 0 To UBound($matches) - 1
              GUICtrlSetData($hProgress, Number($matches[$step]))
            Next
          EndIf
          [color="#FF0000"]GUICtrlSetData($hEdit, $read, 1)[/color]
        EndIf
      ElseIf $bailout = -1 Then 
         Sleep(9000)
         Exit
      Endif
   $nMsg = GuiGetMsg()
   Select
      Case $nMsg = $GUI_EVENT_CLOSE
         ProcessClose($PID)
         Exit
   EndSelect
WEnd

I didn't test if the results were better if one doesn't peek for data before reading it; it could be that you'd get more realistic progress that way, but the GUI message loop wouldn't be progressed while AutoIt was blocked...

Try printong an explicit carriage return(chr(13)) after setting the GUI data string highlighted above(i.e GUICtrlSetData($hEdit, $read & chr(13)), 1))

Edited by TheOrignl

Managing the complexities of our daily lives is always our own responsibility; Allowing God to help us and accepting His guidance is our choice. The best choice!

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  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...