StdoutRead bzw. StderrRead Progress formatieren (wie in Standard CMD)

  • Hey Leute,

    ich hoffe der Titel ist nicht allzu daneben. Mir ist leider kein besserer eingefallen.
    Ich habe ein Programm, dass an einer Stelle mit Hilfe von wget.exe Datei(en) herunterlädt.

    Aus kosmetischen (CMD Window nicht so "hübsch") und praktischen Gründen (wenn es keine neuere Datei gibt, ist das CMD so schnell wieder geschlossen, dass man nicht checkt was geht) lasse ich den Output in der GUI anzeigen.

    In der Kommandozeile sieht das bei wget so aus:

    Spoiler anzeigen
    Code
    --2014-05-11 20:10:07--  http://www.speedtest.qsc.de/100MB.qsc
    Resolving www.speedtest.qsc.de... 195.90.7.115
    Connecting to www.speedtest.qsc.de|195.90.7.115|:80... connected.
    HTTP request sent, awaiting response... 200 OKLength: 104857600 (100M)Saving to: `100MB.qsc'
    100%[======================================>] 104,857,600 3.07M/s   in 34s
    2014-05-11 20:10:41 (2.95 MB/s) - `100MB.qsc' saved [104857600/104857600]

    Im StderrRead (das Programm schreibt Messages nicht zu Stdout sondern zu Stderr) sieht es hingegen so aus

    Spoiler anzeigen

    Dadurch musste ich schon das Limit der EditControl anpassen. Ein bar- Progress wie im Original wäre mir aber lieber.

    Das Handbuch sagt dazu:

    ‘--progress=type’

    Select the type of the progress indicator you wish to use. Legal indicators are “dot” and “bar”.
    The “bar” indicator is used by default. It draws an ASCII progress bar graphics (a.k.a “thermometer” display) indicating the status of retrieval. If the output is not a TTY, the “dot” bar will be used by default.
    Use ‘--progress=dot’ to switch to the “dot” display. It traces the retrieval by printing dots on the screen, each dot representing a fixed amount of downloaded data.
    When using the dotted retrieval, you may also set the style by specifying the type as ‘dot:style’. Different styles assign different meaning to one dot. With the default style each dot represents 1K, there are ten dots in a cluster and 50 dots in a line. The binary style has a more “computer”-like orientation—8K dots, 16-dots clusters and 48 dots per line (which makes for 384K lines). The mega style is suitable for downloading large files—each dot represents 64K retrieved, there are eight dots in a cluster, and 48 dots on each line (so each line contains 3M). If mega is not enough then you can use the giga style—each dot represents 1M retrieved, there are eight dots in a cluster, and 32 dots on each line (so each line contains 32M).
    Note that you can set the default style using the progress command in .wgetrc. That setting may be overridden from the command line. The exception is that, when the output is not a TTY, the “dot” progress will be favored over “bar”. To force the bar output, use ‘--progress=bar:force’.

    Also --progress=bar:force :party:
    So weit so gut...
    aber :S
    dann schreibt es die Bar sehr weit in die Breite und dann irgendwann in der nächsten Zeile fort :huh:

    Ich weiß (noch) nicht, wie ich die Punkte verwenden könnte um eine GUI-Progress-Bar darzustellen. Das würde aber auch nur bedingt weiterhelfen, da mir dann Meldungen wie "saved" "fully retrieved" oder "not newer nothing to do" entgehen. Ausserdem würde das dann massiven Einsatz von StringInString oder StringRegEx bedürfen und da bin ich gerade nicht fit genug drin.

    Hat noch jemand eine Idee oder einen Tipp?

    P.S. Hier der Quellcode für die Passage

    Spoiler anzeigen
    [autoit]

    #include <GuiConstants.au3>
    #include <ColorConstantS.au3>
    #include <Constants.au3>
    GuiCreate("STDIO Window", 425, 322,(@DesktopWidth-425)/2, (@DesktopHeight-362)/2 , $WS_OVERLAPPEDWINDOW + $WS_VISIBLE + $WS_CLIPSIBLINGS)
    $cID_Output = GuiCtrlCreateEdit("", 0, 10, 423, 260, BitOR($ES_WANTRETURN, $WS_VSCROLL, $WS_HSCROLL, $ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))
    GUICtrlSetLimit(-1, 0xF423F)
    GUICtrlSetBkColor(-1, $COLOR_Black)
    GUICtrlSetColor(-1, $COLOR_WHITE)
    _readTest()
    Sleep(10000)

    [/autoit] [autoit][/autoit] [autoit]

    Func _readTest()
    Local $iPID = Run(@ComSpec & " /c .\wget.exe --progress=bar:force -N -c http://www.speedtest.qsc.de/10MB.qsc", "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
    Local $sOutput = ""
    While 1
    $sErrOutput = StderrRead($iPID)
    If @error Then ; Exit the loop if the process closes or StderrRead returns an error.
    ExitLoop
    EndIf
    GUICtrlSetData($cID_Output, $sErrOutput, 1)
    WEnd
    EndFunc

    [/autoit]
  • Wofür brauchst du überhaupt die graphische Anzeige (in Form von Text) des Fortschritts? Soweit ich das verstehe sollte es reichen den Error-Stream zeilenweise auszulesen, die Prozentzahl herauszufiltern (dafür braucht man auch nur ganz wenig StringInStr bzw. regex) und diesen dann an eine ProgressBar weiterzuleiten. Und was genau meinst du mit den Meldungen, die dir dann entgehen?

  • Hi James,

    danke für deine Antwort.
    Wie lese ich denn den Stderr Zeilenweise aus?
    Pro While Runde liest er immer nur einen Teil einer Zeile...

    Meintest du vielleicht ich soll pro Runde nach xxx% suchen?

  • Meintest du vielleicht ich soll pro Runde nach xxx% suchen?


    Das wäre wahrscheinlich am einfachsten. Solange sonst keine Prozentzahlen auftauchen sollte das kein Problem sein.
    Mit StringRegExp würde das übrigens so aussehen:

    [autoit]

    StringRegExp($var, "(\d{1,3})%", 3)

    [/autoit]
  • Ist lange her, dass ich RegEx ansatzweise kapiert habe. Inzwischen habe ich das komplett vergessen.
    Der von Dir vorgeschlagene Test setzt @error auf 1 und liefert keine Ergebnisse...

    Für diesen Ansatz würde ich noch recht viel und detaillierte Hilfe brauchen...

    Ich fürchte auch, dass es das Skript sehr "fett" macht, wenn ich den Stream ständig mit StringRegExp behandle und dann das Array verarbeite.

    Eventuell ist ein anderer Ansatz hier sparsamer...

    Edit:

    die Querlaufende Bar sieht, wenn man den Inhalt des Edits in den Texteditor kopiert, so aus:

    Spoiler anzeigen

    Man müsste also nur schaffen, dass die Zeile im Edit an der richtigen Stelle umbricht. Den @CRLF scheint das Edit ja zu empfangen, sonst würd ein c&p in den Editor das nicht so umbrechen - oder?

    Einmal editiert, zuletzt von Hakeem (11. Mai 2014 um 22:44)

  • Der von Dir vorgeschlagene Test setzt @error auf 1 und liefert keine Ergebnisse...

    Naja, du hast ja selbst gesagt, dass 1x StderrRead einem Teil einer Zeile entspricht, somit kann auch nicht immer eine Prozentzahl gefunden werden. Außerdem dauert 1% wahrscheinlich auch länger als ein Schleifendurchlauf, weshalb StderrRead nicht immer neuen Text zurück gibt.

    Ich fürchte auch, dass es das Skript sehr "fett" macht, wenn ich den Stream ständig mit StringRegExp behandle und dann das Array verarbeite.

    Den Stream auszulesen + RegExp + eventuelles Update der Progressbar sind zusammen ca. 5 Zeilen, ich denke "sparsamer" geht es nicht wirklich. :D Es sei denn du meinst damit etwas anderes...

  • In der Zwischenzeit hatte ich meinen vorherigen Post editiert.

    Mit fett meinte ich nicht die Anzahl Codezeilen sondern die Rechenschritte währen der Ausführung.

    Für heute mach ich erst mal Schluss.
    Danke für deine Hilfe. Hoffe die nächsten Tage wieder Zeit zu finden um weiter zu basteln und die "fünf Zeilen" zu erdenken...


    Edit:
    Konnte es doch nicht lassen :rolleyes:

    Also dein StringRegExp funktioniert - richtig angewendet - schon.
    Bekomme jetzt mit

    [autoit]


    $a_Prozent = StringRegExp($sErrOutput, "(\d{1,3})%",3)
    If IsArray($a_Prozent) Then
    $i_Prozent = $a_Prozent[UBound($a_Prozent)-1]
    Else
    $i_Prozent = ""
    EndIf

    [/autoit]

    pro Runde die letzte übermittelte Zahl. Das ist genau genug.
    Nur die anderen Meldungen von wget hätte ich eben auch gerne. Also wenn keine neuere Datei auf dem Server liegt usw.

    Noch jemand ne Idee, wie ich daran komme? Etwa über eine weitere Prüfung nach predefinierten Strings :wacko:

    Einmal editiert, zuletzt von Hakeem (11. Mai 2014 um 23:44)

  • Link mal deine wget.exe damit wir testen können.

    eventuell geht das ganze viel einfacher ohne wget.exe oder muss es zwingend damit Dateien laden?

    [autoit]

    $hDownload = InetGet("http://www.speedtest.qsc.de/10MB.qsc", "10MB.qsc", 1, 1)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $Prozent = 0
    Do
    If InetGetInfo($hDownload, 1) > 0 Then $Prozent = Round(InetGetInfo($hDownload, 0) / InetGetInfo($hDownload, 1) * 100, 1)
    ConsoleWrite($Prozent & "%" & @CR)
    Sleep(10)
    Until InetGetInfo($hDownload, 2)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    ConsoleWrite(InetGetInfo($hDownload, 1) & @CR) ;Filesize in Bytes
    ConsoleWrite(InetGetInfo($hDownload, 0) & @CR) ;Geladene Bytes

    [/autoit]