Jump to content

Recommended Posts

Posted

I have run into a problem with Run(...,  $STDOUT_CHILD)  and then calling StdOutRead($pid) in a loop to get all data.
I'm starting the same child application over and over, collecting and then evaluating the child's output.
At a certain point Autoit freezes. It appears to be a random deadlock.
The deadlock does not happen when I do ProcessWaitClose($pid) and afterwards StdOutRead($pid). But the helpfile says it's advisable to read STDOUT in a loop to get all data.
Here's the minimum example code. Make sure to watch the console output e.g. in SCiTE. It will stop spewing new output after a few seconds or minutes:

; AutoIt Version: 3.3.14.2
; Script Function: Autoit sometimes deadlocks (stops responding) when using Run() repeatedly with a StdoutRead loop.
; Just leave this running for a certain time, it will freeze eventually.
#include <AutoItConstants.au3>
While True
    $pid = Run('tasklist.exe', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)
    $sOutput = ""
    Do
        $sOutput &= StdoutRead($pid) ; collect new output
    Until @error ; EOF reached
    ProcessWaitClose($pid) ; These two don't make a difference...
    StdioClose($pid)       ; ... you can leave them out
    ConsoleWrite($sOutput)
    Sleep(50)
WEnd

Am I doing something wrong here or is there a bug in AutoIT?

Posted (edited)
1 hour ago, mbit90 said:

Make sure to watch the console output e.g. in SCiTE. It will stop spewing new output after a few seconds or minutes

the title says 'freezes' did you mean SciTE crashed and became unresponsive which require termination/end task from task manager?

code above only stopped producing console output after about 47seconds, it pretty common to me -still have control over SciTE. need to terminate by heading over to 'tools > stop executing'

i don't know why but try this you'll get the same thing -console write would halt.

While 1
    ConsoleWrite('!>!'&@ScriptLineNumber&':'&$str&' please stop'&@CRLF) ;Read/Brown
WEmd

 

Edited by zeenmakr
Posted
6 minutes ago, Danp2 said:

The issue appears to be that the launched application doesn't exit, so your code gets stuck in a loop. Change @SW_HIDE to @SW_SHOW in your code and you'll see what I mean.

like this? still freezes up

#include <AutoItConstants.au3>

$hGui = GUICreate('')
GUISetState(@SW_SHOW, $hGui)

While True
    $pid = Run('tasklist.exe', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)
    $sOutput = ""
    Do
        $sOutput &= StdoutRead($pid) ; collect new output
    Until @error ; EOF reached
    ProcessWaitClose($pid) ; These two don't make a difference...
    StdioClose($pid)       ; ... you can leave them out
    ConsoleWrite($sOutput)
    Sleep(50)
WEnd

 

Posted
6 hours ago, zeenmakr said:

the title says 'freezes' did you mean SciTE crashed and became unresponsive which require termination/end task from task manager?

Nope, not SCiTE freezes, the AutoIT process (the runtime interpreter) freezes. And no crashes. A freeze means the program stops doing anything, it deadlocks, and becomes unresponsive (e.g. the try icon dos not react to anything in this example). You can in fact see the same result without running in SCite but directly. You just don't get the ConsoleWrite() output.

6 hours ago, zeenmakr said:

i don't know why but try this you'll get the same thing -console write would halt.

While 1
    ConsoleWrite('!>!'&@ScriptLineNumber&':'&$str&' please stop'&@CRLF) ;Read/Brown
WEmd

$str is not defined. But when I remove $str, Autoit Crashes after a few minutes with a DialogBox saying "Error allocating memory", which is also strange but surely a different bug?

1 minute ago, Danp2 said:

The issue appears to be that the launched application doesn't exit, so your code gets stuck in a loop. Change @SW_HIDE to @SW_SHOW in your code and you'll see what I mean.

When I tried this, AutoIt froze again, but the last console window that popped up closed. However, tasklist.exe still ran. Terminating tasklist.exe did not un-freeze AutoIt.
Note that the call to ProcessWaitClose($pid) does not cause the issue -- it can be removed from the script with the same result. It's just there for 'best practice' reasons.
It's also not tasklist.exe misbehaving in some way, I tried this with other console applications as well with the same result.

Posted
10 minutes ago, zeenmakr said:

would result in continuous cmd window popingup

Exactly... that way you can observe the program when it fails to exit.

17 minutes ago, mbit90 said:

Terminating tasklist.exe did not un-freeze AutoIt.

From what I can see, after the initial "hang", the launched process will continue to hang each time it is launched. Here's my version of your code --

#include <AutoItConstants.au3>
$x = 1

While True
    $pid = Run('tasklist.exe', @ScriptDir,  @SW_HIDE, $STDOUT_CHILD)

    If @error Then Exit

    $sOutput = ""
    $y = 0
    Do
        $y += 1

        If $y > 500000 Then
            ProcessClose($pid)
            ExitLoop
        EndIf

;       Sleep(100)
        $sOutput &= StdoutRead($pid) ; collect new output
    Until @error ; EOF reached
    ConsoleWrite("$y=" & $y & @CRLF)
    ProcessWaitClose($pid) ; These two don't make a difference...
    StdioClose($pid)       ; ... you can leave them out
    ConsoleWrite("$x=" & $x & @CRLF)
;   ConsoleWrite($sOutput)
    $x += 1
    Sleep(50)
WEnd

And here's the console output from the most recent run --

$y=170008
$x=1
$y=209266
$x=2
$y=206772
$x=3
$y=206552
$x=4
$y=208768
$x=5
$y=201445
$x=6
$y=207141
$x=7
$y=200126
$x=8
$y=204915
$x=9
$y=204160
$x=10
$y=208952
$x=11
$y=208278
$x=12
$y=208166
$x=13
$y=200109
$x=14
$y=208952
$x=15
$y=204353
$x=16
$y=211114
$x=17
$y=203153
$x=18
$y=202704
$x=19
$y=199369
$x=20
$y=208926
$x=21
$y=201927
$x=22
$y=208349
$x=23
$y=211657
$x=24
$y=213872
$x=25
$y=209144
$x=26
$y=211106
$x=27
$y=202671
$x=28
$y=203840
$x=29
$y=206928
$x=30
$y=208421
$x=31
$y=209180
$x=32
$y=201213
$x=33
$y=205221
$x=34
$y=197454
$x=35
$y=202601
$x=36
$y=211849
$x=37
$y=205381
$x=38
$y=198597
$x=39
$y=195326
<snip>
$x=328
$y=214865
$x=329
$y=202048
$x=330
$y=202573
$x=331
$y=212213
$x=332
$y=198373
$x=333
$y=206837
$x=334
$y=500001
$x=335
$y=500001
$x=336
$y=500001
$x=337
$y=500001
$x=338
$y=500001
$x=339
$y=500001
$x=340
$y=500001
$x=341
$y=500001
$x=342
$y=500001
$x=343
$y=500001
$x=344
$y=500001
$x=345
$y=500001
$x=346
$y=500001
$x=347
$y=500001
$x=348
$y=500001
$x=349
$y=500001
$x=350
$y=500001
$x=351
$y=500001
$x=352
$y=500001
$x=353
$y=500001
$x=354
$y=500001
$x=355
$y=500001
$x=356
$y=500001
$x=357
$y=500001
$x=358
$y=500001
$x=359
$y=500001
$x=360
$y=500001
$x=361
$y=500001
$x=362
$y=500001
$x=363
$y=500001
$x=364
$y=500001
$x=365
$y=500001
$x=366
$y=500001
$x=367

 

Posted (edited)

I would structure the logic a bit differently than in the original post.  Unless there is a reason to look at the output before the command finishes, then it's much easier to just grab the complete output of the command after the command finishes.  The example below runs the command in a for next loop in order not to have an endless loop.  No matter how many times it loops, it shouldn't freeze.

#include <Constants.au3>

cmd_output_example()

Func cmd_output_example()
    Local $iPID = 0

    For $i = 1 To 15
        ;execute command
        $iPID = Run(@ComSpec & ' /c tasklist.exe', "", @SW_HIDE, $STDERR_MERGED)
        If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "An error occurred executing command.")

        ;wait for process to end
        ProcessWaitClose($iPID)

        ;Display output
        ConsoleWrite("Tasklist execution #" & $i & @CRLF)
        ConsoleWrite(StdoutRead($iPID) & @CRLF)
    Next
EndFunc

 

Edited by TheXman
Change script to display output each loop instead of aggregating it and displaying it once.
Posted


 

12 hours ago, Danp2 said:

From what I can see, after the initial "hang", the launched process will continue to hang each time it is launched. Here's my version of your code --

#include <AutoItConstants.au3>
$x = 1

While True
    $pid = Run('tasklist.exe', @ScriptDir,  @SW_HIDE, $STDOUT_CHILD)

    If @error Then Exit

    $sOutput = ""
    $y = 0
    Do
        $y += 1

        If $y > 500000 Then
            ProcessClose($pid)
            ExitLoop
        EndIf

;       Sleep(100)
        $sOutput &= StdoutRead($pid) ; collect new output
    Until @error ; EOF reached
    ConsoleWrite("$y=" & $y & @CRLF)
    ProcessWaitClose($pid) ; These two don't make a difference...
    StdioClose($pid)       ; ... you can leave them out
    ConsoleWrite("$x=" & $x & @CRLF)
;   ConsoleWrite($sOutput)
    $x += 1
    Sleep(50)
WEnd

And here's the console output from the most recent run --

Hmm... so you inserted a watchdog sort of thing into the loop, in case StdoutRead does not give @error when it should. Nice idea. However, when I run it, it just freezes again instead of giving the $y=500001 outputs. AutoIT does not accumulate any cycles when I check in Process Hacker, meaning it's not stuck in a loop, but an actual deadlock.

 

@TheXman, your example works just fine for most applications, but the point of my original post was to demonstrate that AutoIT freezes when calling StdoutRead in a loop.

Calling StdoutRead in a loop is mentioned as good practice in the help file, so it should not cause the runtime to deadlock.
Furthermore, as you mentioned, there might be reasons to "stream" the output to the host application continuously. I currently build such an application and stumbled upon this bug, then constructed the minimal example to isolate the issue.

I might not have made this clear in my original post, if so, I'm sorry :D
This was meant to be a bug report, kind of. Is there a better way of reporting this issue to the devs?
I'm still interested in any intermediate workarounds that call StdoutRead repeatedly without freezing though :D

cheers

Posted (edited)

There's no bug.  You just need to tighten up your logic, or should I say, make it a little more robust.  Here's a UDF I wrote to capture cmd output as it happens.  I've used it for years and it has never frozen up on me.  However, I've really never had the need to run it in a tight loop.  But it doesn't seem to have any issue in my example below.  If you are wondering why there is a loop to wait for output before reading the output, it is because it was written for an application that took 1-2 seconds before it started generating output.

#include <Constants.au3>

cmd_output_example()

Func cmd_output_example()
    Local $sOutput = ""

    For $i = 1 To 10
        ;execute command
        $sOutput = _RunCaptureOutput("tasklist.exe", "")
        If @error Then Exit MsgBox($MB_ICONERROR, "ERROR", "An error occurred executing command. @error = " & @error)

        ;Display output
        ConsoleWrite("Tasklist execution #" & $i & @CRLF)
        ConsoleWrite($sOutput & @CRLF)
    Next
EndFunc

;==========================================================================
; Function Name:    _RunCaptureOutput()
; Description:      Execute a command and capture the output
; Parameter(s):     $strCmd, command to be executed
;                   $strWorkingDir, optional, working directory
;                   $iTimeoutSecs, optional, timeout in seconds
; Requirement(s):   None
; Return Value(s):  Success: Output of the executed command
;                   Failure: "" and sets @error (see notes)
; Author(s):        TheXman
; Note(s):          @error = 1, Error executing the RUN function
;                   @error = 2, Process closed before displaying any output
;                   @error = 3, Timed out before displaying any output
;==========================================================================
Func _RunCaptureOutput($strCmd, $strWorkingDir = @WorkingDir, $iTimeoutSecs = 5)
    Local $intPID     = 0
    Local $strOutput  = ""
    Local $hndTimer   = -1

    ;execute command
    $intPID = Run($strCmd, $strWorkingDir, @SW_HIDE, $STDERR_MERGED)

    ;return if error
    If @error Then
        ConsoleWrite("Error: Unable to execute command - " & $strCmd & @CRLF)
        Return SetError(1, 0, "")
    EndIf

    ; loop until there is data to display, process closes, or timed out
    $hndTimer = TimerInit()
    While Not StdoutRead($intPID, True)
        ;process still exists
        If ProcessExists($intPID) Then
            ;sleep
            Sleep(250)
        Else
            ;display warning and return
            ConsoleWrite("Warning: Process closed before displaying any output" & @CRLF)
            Return SetError(2,0,"")
        EndIf

        ;If timeout has been reached
        If TimerDiff($hndTimer) > $iTimeoutSecs * 1000 Then
            ;display warning and return
            ConsoleWrite("Warning: Process timed out waiting for output" & @CRLF)
            Return SetError(3,0,"")
        EndIf
    WEnd

    ;loop while there is data to display
    While StdoutRead($intPID, True)
        ;display stdout data
        $strOutput &= StdoutRead($intPID)

        ;sleep for .5 secs
        Sleep(500)
    WEnd

    ;return output
    Return $strOutput
EndFunc

 

Edited by TheXman
Posted

I don't get the full Tasklist output with the Sleeps removed - code like this must not rely on getting the Sleep timings just right.
You can't just assume that when StdoutRead returns an empty string once, that the output is finished. More output may come later. Of course it works with tasklist followed by 500ms of sleeping - in the common case.
The only (intended) reliable indication for end-of-stream seems to be @error after StdoutRead, or am I missing something?

Posted (edited)

I disagree with your assertion regarding timing.  I also don't get any truncation of the tasklist output.  The stdout stays in the buffer until read so I don't know why you aren't seeing the full tasklist output.  My tasklist is pretty large and I get the whole thing each time thru the loops.

My UDF was written to handle the output of the application I was dealing with.  Once it started writing to stdout, it continued until it was done.  If you need something else, then I have given you a pretty good platform to jump off from.

Edited by TheXman
Posted

Well, assume you want the reading of stdout to be fast, then you could not use Sleeping, but you would have to rely only on Locks and Busy waiting. Looking at this from a C programmer perspective.

i get the truncation of the tasklist output only if I remove the Sleeps from your code, and it's perfectly clear why. The last loop...

37 minutes ago, TheXman said:

;loop while there is data to display     While StdoutRead($intPID, True)         ;display stdout data         $strOutput &= StdoutRead($intPID)         ;sleep for .5 secs         Sleep(500)     WEnd

... without the Sleep will collect some initial output into the string, but in the second iteration, StdoutRead returns "" (most likely) and the loop exits (perhaps) without the remainder of output that tasklist has yet to print. It depends on the timing between the two processes and thus has undefined behaviour.

Posted

You could make plenty other changes to the code to make it not work too, so what?  It has a sleep in it because that's the way I wrote it and it worked perfectly for my needs.  AutoIt isn't C so I don't care to look at it from a C-perspective.  If it needs to run like a C application, then write it in C.  I'm showing you how it can be done in AutoIt.  You are starting to try my patience.  So I will just leave it to someone else to entertain your observations, assertions, arguments.  Have a good evening or day, where ever you may be.

Posted

Yep my needs are clearly different. I'm just trying to stick to the topic, which is about the very simple example code in my first post, and that it should be working according to the help file, while it causes autoit to deadlock.

Good night to you as well.

Posted (edited)

I'v made few tests with the code.

The code from the first post is freezing somewhere in between 45 and 200 rounds.

I'v tested the example code from TheXman, and i stopped it after around 700 rounds, because it did not freezed. (i changed the for loop into a while loop )

Then i took the code from the 1st post and experimented a bit with it.

As you can see, i tried few things: (some things are in other posts  too)

#include <GuiEdit.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>

    Global $hGUI = GUICreate("CMD", 500, 400, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_THICKFRAME), BitOR($WS_EX_ACCEPTFILES, $WS_EX_WINDOWEDGE))
    Global $g_idMemo = GUICtrlCreateEdit("", 0, 31, 499, 349)

    GUISetState(@SW_SHOW)

Local $i=0,$j=0, $k=0
While True
    $k=0
    $j=$j+1
    $pid = Run('tasklist.exe', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)
    sleep (200)
    $sOutput = ""
    ;If ProcessExists($pid) Then
        $i=$i+1
        WinSetTitle ($hGUI,"",$i & "/" & $j & "/" & $pid)
        Do
            $k=$k+1
            $sOutput &= StdoutRead($pid) ; collect new output
            if $k>540000 then
                ConsoleWrite ("emergency exit" & @CRLF)
                ExitLoop
            EndIf
        Until @error ; EOF reached
        ;StdioClose($pid)   ; ... you can leave them out
        ;ProcessWaitClose($pid) ; These two don't make a difference...
        MemoWrite("",1)
        MemoWrite($sOutput)
    ;EndIf
    Sleep(50)
WEnd


Func MemoWrite($sMessage = "", $clr = 0)
    Local $CRLF = ""

    If $clr = 1 Then
        GUICtrlSetData($g_idMemo, "")
    Else
        $CRLF = @CRLF
    EndIf

    GUICtrlSetData($g_idMemo, $sMessage & $CRLF, 0)
EndFunc   ;==>MemoWrite

P.S. i'v added a gui and an edit field, where the output is written.

This code is running, at the moment of writing, with 1500 loops without freezing.

The important part here is the Sleep (200) just after the Run('tasklist.exe") line 

(edit #5: i'v just tried out to increase the sleep(50) and the freezing have started (not using the sleep (200) line), so it is not up to this)

If you lower it, the freezing may start happening  - the lower the number - the sooner the freezes.

The emergency exit has not been reached in the normal run, but only with the lowered sleep amount.

If a freeze (and it is not the script which is freezing, just the capturing of the output with the StdOutRead) and this, @DanP2, has allready mentioned: All consecutive run calls will fail to capture the output.

Why is this happening - IDK, maybe a bug, but the question is, is it a bug in autoIt or an windows bug ... 

(currently the loop has reached 4200 (after few edits) as it is running in the background).

Maybe someone wants to open a ticket in the bugtracker, so that the developers may look into it (if it is a bug at all) ?

 

Edited by Dan_555

Some of my script sourcecode

  • 4 years later...
Posted
On 9/26/2020 at 11:38 AM, Dan_555 said:

Guys, this is an auto'it forum where people try to help others. (at least that is my perspective).

Please concentrate on problem-solving things, not on personal viewpoints.

I'v made few tests with the code.

The code from the first post is freezing somewhere in between 45 and 200 rounds.

I'v tested the example code from TheXman, and i stopped it after around 700 rounds, because it did not freezed. (i changed the for loop into a while loop )

Then i took the code from the 1st post and experimented a bit with it.

As you can see, i tried few things: (some things are in other posts  too)

#include <GuiEdit.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>

    Global $hGUI = GUICreate("CMD", 500, 400, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_SIZEBOX, $WS_THICKFRAME), BitOR($WS_EX_ACCEPTFILES, $WS_EX_WINDOWEDGE))
    Global $g_idMemo = GUICtrlCreateEdit("", 0, 31, 499, 349)

    GUISetState(@SW_SHOW)

Local $i=0,$j=0, $k=0
While True
    $k=0
    $j=$j+1
    $pid = Run('tasklist.exe', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)
    sleep (200)
    $sOutput = ""
    ;If ProcessExists($pid) Then
        $i=$i+1
        WinSetTitle ($hGUI,"",$i & "/" & $j & "/" & $pid)
        Do
            $k=$k+1
            $sOutput &= StdoutRead($pid) ; collect new output
            if $k>540000 then
                ConsoleWrite ("emergency exit" & @CRLF)
                ExitLoop
            EndIf
        Until @error ; EOF reached
        ;StdioClose($pid)   ; ... you can leave them out
        ;ProcessWaitClose($pid) ; These two don't make a difference...
        MemoWrite("",1)
        MemoWrite($sOutput)
    ;EndIf
    Sleep(50)
WEnd


Func MemoWrite($sMessage = "", $clr = 0)
    Local $CRLF = ""

    If $clr = 1 Then
        GUICtrlSetData($g_idMemo, "")
    Else
        $CRLF = @CRLF
    EndIf

    GUICtrlSetData($g_idMemo, $sMessage & $CRLF, 0)
EndFunc   ;==>MemoWrite

P.S. i'v added a gui and an edit field, where the output is written.

This code is running, at the moment of writing, with 1500 loops without freezing.

The important part here is the Sleep (200) just after the Run('tasklist.exe") line 

(edit #5: i'v just tried out to increase the sleep(50) and the freezing have started (not using the sleep (200) line), so it is not up to this)

If you lower it, the freezing may start happening  - the lower the number - the sooner the freezes.

The emergency exit has not been reached in the normal run, but only with the lowered sleep amount.

If a freeze (and it is not the script which is freezing, just the capturing of the output with the StdOutRead) and this, @DanP2, has allready mentioned: All consecutive run calls will fail to capture the output.

Why is this happening - IDK, maybe a bug, but the question is, is it a bug in autoIt or an windows bug ... 

(currently the loop has reached 4200 (after few edits) as it is running in the background).

Maybe someone wants to open a ticket in the bugtracker, so that the developers may look into it (if it is a bug at all) ?

 

Sorry for my English, translated by Google.

Search for the error of Autoit freezing with the operator "stdoutread"brought me to this topic. What can I say, but first about my configuration:
Autoit 3.3.14
Win7x64
CPU Core-i7 CPU, 32Gb RAM
Approximately the following program code froze for me. I became interested in the reasons. After each of the key operators, I put the so-called marks in the form of console and found that the freezing occurs quite quickly from 10 minutes to 1 hour in the inner loop (where the operator is stdoutread). In the example above, the inner loop is the Do/Until operators.
In general, I will not keep you in suspense - I am not 100% sure yet, but my problem was solved* by inserting the Sleep(20) delay into this inner loop.

Yes, I will immediately make a reservation - the Sleep delay in the external operator (in the example, it is While/Wend) was initially set for me, I needed it for my purposes and the delay was 20 seconds. Sleep(20000), but it did not help to get rid of the freezes.

* - At least I assume and hope so, because more than 2 hours have passed and in my case there are 437 iterations and no freezes.

By the way, I draw attention to this quote: "The important part here is the Sleep (200) just after the Run('tasklist.exe") line " and I repeat the operator sleep, which is mentioned in the quote, was initially in the outer loop and this did not help to solve the problem. The problem was solved precisely by the fact that the operator sleep was located in the inner loop (Between Do/Until in Example above)

Posted (edited)

Am using _RunWaitEx() and uses Sleep(1). Running _RunWaitEx('tasklist.exe') as the example and no problems. Give it a try ?

9 hours ago, daledale said:

Autoit 3.3.14

it does use ternary operators so, replace with _Iif() if v3.3.14 does not understand/have ternary operators.
Am using v3.3.16.1

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)
7 hours ago, argumentum said:

Am using _RunWaitEx() and uses Sleep(1). Running _RunWaitEx('tasklist.exe') as the example and no problems. Give it a try ?

That's the thing, you suggest inserting the _RunWaitEx()  operator instead of Run() into the so-called outer loop, because initially for me, as well as in the example above, Run() is in the outer loop. But this does not solve the problem of hanging. I repeat, in my program the Sleep() operator was initially in the outer loop already.
I repeat, the problem is solved if and only if the sleep delay is located in the inner loop, near StdoutRead()

Ok, to make it clearer or, as we say: "Instead of thousand words" - two versions of my code. Explanation - I have two gateways in the local network and I want to see online which gateway is currently enabled. Below are two versions of the program. The 1st code - hangs after a random time, the 2nd - does not.

; freezes randomly
local $fDiff=0, $pid=0, $hTimer=0, $line=""

While 1
    $pid = Run("ipconfig", "", @SW_HIDE, 0x2)
    $line = ""
    $hTimer = TimerInit()
    While 1
        $fDiff = TimerDiff($hTimer)
        $line &= StdoutRead($pid)
        If @error or $fDiff>50 Then ExitLoop
    Wend
    if StringInStr($line,'0.1'&@CRLF)>1 then TraySetIcon("icon1.ico")
    if StringInStr($line,'0.2'&@CRLF)>1 then TraySetIcon("icon2.ico")
    sleep(20000)
WEnd

 

; works fine
local $fDiff=0, $pid=0, $hTimer=0, $line=""

While 1
    $pid = Run("ipconfig", "", @SW_HIDE, 0x2)
    $line = ""
    $hTimer = TimerInit()
    While 1
        $fDiff = TimerDiff($hTimer)
        sleep(20)
        $line &= StdoutRead($pid)
        If @error or $fDiff>50 Then ExitLoop
    Wend
    if StringInStr($line,'0.1'&@CRLF)>1 then TraySetIcon("icon1.ico")
    if StringInStr($line,'0.2'&@CRLF)>1 then TraySetIcon("icon2.ico")
    sleep(20000)
WEnd

The parameter with the timer, as an additional condition for exiting the cycle = 50 - was selected experimentally. In principle, it was possible to do without this condition, but just in case, this was also done at the stage of searching for a hang and remained so.

Theoretically, you can do without the timer, and then the program will take on an even more compact form.

; maybe works fine
local $pid=0, $line=""

While 1
    $pid = Run("ipconfig", "", @SW_HIDE, 0x2)
    $line = ""
    While 1
        sleep(20)
        $line &= StdoutRead($pid)
        If @error Then ExitLoop
    Wend
    if StringInStr($line,'0.1'&@CRLF)>1 then TraySetIcon("icon1.ico")
    if StringInStr($line,'0.2'&@CRLF)>1 then TraySetIcon("icon2.ico")
    sleep(20000)
WEnd

 

Edited by daledale

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
  • Recently Browsing   0 members

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