Jump to content

Variable for run output has to be redifined?


Recommended Posts

I'm reading an SNMP MIB from a DOS program called snmputil. This does work and it reads into my $line variable properly. I want to read it once, wait 1 second, and read it again so that I can see how much it changed.

BUT... this only works if I redefine the $SNMPget variable AGAIN before the second read. Why is that, what am I doing wrong?

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 10.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

Local $t, $line, $result1 = "", $result2 = ""


While 1
    Sleep(100)
    $line = StdOutRead( $SNMPget )
    If @error Then ExitLoop
    $result1 = $line
WEnd
$t=StringInStr($result1, "Counter32")

sleep(1000)

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 710.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

While 1
    Sleep(100)
    $line = StdOutRead( $SNMPget )
    If @error Then ExitLoop
    $result2 = $line
WEnd
$t=StringInStr($result1, "Counter32")

MsgBox(0, "Octets", StringMid($result2, $t+10) & StringMid($result1, $t+10 ) )
MsgBox(0, "works? ", (StringMid($result2, $t+10) - StringMid($result1, $t+10))*8/1000000 )


;MsgBox(0, '', StringMid($snmp, 1))

If I don't define the $SNMPget variable a second time, my $line variable is empty on the second read.

Link to comment
Share on other sites

  • Developers

If I don't define the $SNMPget variable a second time, my $line variable is empty on the second read.

What exactly doesn't work (show script) and what do you do to make it work?

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

What exactly doesn't work (show script) and what do you do to make it work?

The code I uploaded does work. It displays two variables, $result2 and $result1.

You'll notice that the $SNMPget variable is defined twice, exactly the same. Second one after my sleep(1000), before the second WHILE loop.

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 76.7.88.30 time .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

If I remove the second definition (which I think I should be able to do), then instead of displaying two variables, it will only display $result1.

Does that make sense?

Edited by SystemWontAccept
Link to comment
Share on other sites

  • Developers

The code I uploaded does work. It displays two variables, $result2 and $result1.

You'll notice that the $SNMPget variable is defined twice, exactly the same. Second one after my sleep(1000), before the second WHILE loop.

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 76.7.88.30 time .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

If I remove the second definition (which I think I should be able to do), then instead of displaying two variables, it will only display $result1.

Does that make sense?

Not sure yet... show me the script you think should work to avoid wrong guessing on my part. :D

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Not sure yet... show me the script you think should work to avoid wrong guessing on my part. :D

This code, with the remarked out $SNMPget variable, only displays $result1.

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 10.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

Local $t, $line, $result1 = "", $result2 = ""


While 1
    Sleep(100)
    $line = StdOutRead( $SNMPget )
    If @error Then ExitLoop
    $result1 = $line
WEnd
$t=StringInStr($result1, "Counter32")

sleep(1000)

;Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 10.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

While 1
    Sleep(100)
    $line = StdOutRead( $SNMPget )
    If @error Then ExitLoop
    $result2 = $line
WEnd
$t=StringInStr($result1, "Counter32")

MsgBox(0, "Octets", StringMid($result2, $t+10) & StringMid($result1, $t+10 ) )
Edited by SystemWontAccept
Link to comment
Share on other sites

  • Developers

Ok so it really is one command you want to capture the total output of.

You need to concatenate it all so try:

Local $SNMPget = Run (@ComSpec & " /c c:\windows\system32\snmputil.exe get 10.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

Local $t, $line, $result1 = "", $result2 = ""


While 1
    Sleep(100)
    $line = StdOutRead( $SNMPget )
    If @error Then ExitLoop
    $result1 &= $line
WEnd

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Some clarification into the way that StdoutRead and its relatives work:

To human eyes it seems like a program that writes output to a console (e.g. to STDOUT) writes it all in one blurt, and even if it doesn't we'd tend to think that it was an artifact of the console window not drawing fast enough. In actuality, between program idiosyncrasies and the buffering process a program may send even a small amount of output in several writes, and even if you delay reading it you can't rely on a single read getting everything that was written.

By default a call to StdoutRead grabs all output of the child process available. The way that you know if that's all output that will ever be forthcoming is by testing the value of @error immediately after StdoutRead; if@error is zero then there's still more data to be had. Your code takes this into account (it exits the loop once @error is non-zero) but the problem is that on every loop it throws away what was read on previous loops; this is what Jos means by concatenation and why his example shows using the &= operator. Your code keeps the next-to-the-last read as the captured data, but it's possible that your child program may have an empty, seemingly empty or incomplete write after the data you're really looking for; better to use Jos's method.

Regarding your multiple defines, I'm assuming you need to call your utility program twice to get two results, and that's what you're doing with two calls to Run. Your StdoutRead loops are designed to exit when StdoutRead sets @error to a non-zero value, and (assuming you've run a valid, output producing command) when that happens it almost certainly means the child program has exited. That being the case, in your second example your util exits during the first loop, so there's never anything to be read in the second loop.

Clear as mud?

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.

Link to comment
Share on other sites

Thanks for noticing the '7', but that's not the problem, just a typo. Good eye. :-)

Dave, your explanation of StdOut is very helpful! A few comments...

1) Absolutely correct, I need to call my utility twice so I can subtract one from the other to calculate the amount of change.

2) I have a question about using &=. I agree, I thought that would be needed but it isn't. Well, I don't think it is. It works most of the time with just =. Meaning it reads my child process properly and I get the expected results (excluding the double variable definition we're discussing of course). Are you stating that the &= is needed? Or that it's simply better syntax? Or that it will change my "works most of the time" to "works *all* of the time"?

3) This is the core of my original question... You said that the first loop exits and therefore there is never anything to read in the second loop. If that is the case, then why does simply redefining the $SNMPget variable (you see where I have it remarked out), why does that make the second loop read. As I said, I know how to fix this so it works...

Redefine the $SNMPget variable before the second loop, it works.

Don't redefine the $SNMPget variable before the second loop, it fails.

What I don't understand is why? It's so crazy to have to define the same variable again, that I'm certain that I'm doing something wrong. That's my question.

Ed

Link to comment
Share on other sites

I think that you need to redefine your variable twice on your 1st posted script because you're waiting StdOut data from a process and once you've received data this process die & its handle too.

Am I wrong?

If I'm right: maybe this script can help you (Done from scratch :D)

Global $result1 = "", $result2 = ""

$result1 = _SNMPget()
sleep(1000)
$result2 = _SNMPget()

If BitAND(IsArray($result1), IsArray($result2)) = 1 Then
    MsgBox(0, "Octets", StringMid($result2[0], $result2[1] + 10) & StringMid($result1[0], $result1[1] + 10))
    MsgBox(0, "works? ", (StringMid($result2[0], $result2[1] + 10) - StringMid($result1[0], $result1[1] + 10)) * 8 / 1000000)
Else
    MsgBox(4096,"Bug", "Are $result# Array?" & @crlf & @crlf & _
            "$result1 = " & IsArray($result1) & @crlf & _
            "$result2 = " & IsArray($result2))
EndIf


;MsgBox(0, '', StringMid($snmp, 1))

Exit

;-Func _SNMPget()
;-
;-Retrieve the data(s) you want and return them into an array
Func _SNMPget()
    Local $result
    Dim $result[2]

    Local $SNMPget = Run(@ComSpec & " /c c:\windows\system32\snmputil.exe get 10.10.10.10 public .1.3.6.1.2.1.2.2.1.10.4", @ScriptDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

    While 1
        Sleep(100)
        $result[0] = StdoutRead($SNMPget)
        If @error Then ExitLoop
    WEnd
    $result[1] = StringInStr($result[0], "Counter32")

    Return $result
EndFunc   ;==>_SNMPget
Edited by taz742
Link to comment
Share on other sites

Thanks Taz,

I like your design better and I've implemented it in my code. But your design does what mine did and that is, it redefines the $SNMPget variable before each use of that same variable. Now, it's less apparent in yours because it's just part of the design. But since we started this as a question on why it has to be defined each time, that question still hasn't been answered.

For that original question, my original code is a better example. Again, if you look at the line that is ;remarked out, between the two While loops... why does that line (that $SNMPget variable) have to redefined for the code to work.

You mentioned that the StdOut process is completed and the process dies and it's handle as well. I've done a message box and the $SNMPget variable (the handle) remains the same. It's a number and that number is the same before and after the first While loop. As I mentioned it's different each run. But it does stay the same *within* the run. Wouldn't that mean the handle is still good?

Anybody know what's causing this?

Thanks again Taz, your code was very helpful.

Ed

Edited by SystemWontAccept
Link to comment
Share on other sites

@SystemWontAccept

The only question I see here is what body-part you're thinking with. Your question doesn't make the slightest sense.

You say in post 9 that you understand that you need to Run() the app twice, yet you continue asking why it doesn't work when you only Run() it once! I mean come on, did you really think that one through?

Link to comment
Share on other sites

I admit this appears confusing but I think if you read it throughly (as I've done dozens of times), you'll see the point. I'm not asking how to fix it, I know how to fix it. I'm saying that the "fix" doesn't make sense. There are thousands of ways to do things wrong, that still appear to work properly. Just because it works, doesn't make it right.

In that same post #9 I said that I can run the same code (two passes)... but if I don't redefine the variable, it fails. Why?

I'm saying that defining the same variable more than once, with the same exact data, shouldn't be necessary.

Please read my post throughly.

Edited by SystemWontAccept
Link to comment
Share on other sites

Yes you fix it by running it a second time. You already know you need to do this so what are you really asking? You seem to miss the point completely.

taz742 already told you, you can only read the data once. You must Run the app again. You say you know this, but still asks about it. Why?

Edited by AdmiralAlkex
Link to comment
Share on other sites

I keep asking because it's you who doesn't seem to understand the question. I have *never* asked how to fix it. In my first post I said "this does work". Then in post #5 (after a question to show the problem), I altered the code so that it *doesn't* work by changing the second $SNMPget variable to a remark. So, in this thread you have post #1 which works, and post #5 which doesn't.

But... Maybe I'm not understanding you either. You say "run it a second time".

I assume you mean run my DOS command? Yes I know I have to run my DOS program a second time. But why doesn't the second run work? The second result is blank if I just leave the $SNMPget variable as is (I mean if I don't redefine it). Why does my DOS program return a result the first time and not the second? The $SNMPget variable is still defined isn't it?

I checked the $SNMPget variable *before* and *after* the first run of my DOS program and it doesn't change.

***** So if the $SNMPget variable hasn't changed, why does it need to be redefined? *****

I did a MsgBox(0, '', $SNMPget) to display the value of the $SNMPget variable both before the first DOS program call, and before the second DOS program call. The $SNMPget variable doesn't *appear* to change. Is there something about the $SNMPget variable that *has* changed? If so, how can I display that change for troubleshooting purposes.

Please be specific. I'm not trying to be a jerk, I'm trying to understand this. I'm trying to learn how/why this works like this.

Don't use the word "it" in your explanation, be specific so can I understand what your saying.

Edited by SystemWontAccept
Link to comment
Share on other sites

Umm right... I'm not the best at explaining things, but here we go.

If we assume you don't "redeclare" the variable this happens=

Run() executes the app once. You Run() snmputil.exe and save the return value, a PID.

Then you have a loop that reads the STDOUT stream from that PID, until an error returns, like the app closed and you read everything it had.

Then you try to read the STDOUT stream again. But wait, you already read everything earlier, so there's nothing fo us now!

You said the variable gave the same number before and after the loop. Well that's because no one changes it.

So then why does no one of us understand the other? I don't know, but I could guess.

You seem to think that writing "$SomeVariable = SomeFunction()" makes SomeFunction "execute" everytime the variable is used. That is not the case, or none of your loops would have worked!

Remember that PID is unique for every process.

What does happen when you write "$SomeVariable = SomeFunction()", is that the Return-value from the function is written to the variable, so to have something to read in the second loop you would have to Run() your app again, save the PID and read that. Like you do when you redeclare the variable you already have.

Did any of this make any sense to you? I hope so. :D

Link to comment
Share on other sites

Maybe I understand now.... You say the PID is unique for every process. That's the same as the handle that Taz mentioned right?

And so my DOS command can only be called once with that $SNMPget variable. Even though the $SNMPget variable is the same, it can't be used again.

Now I understand why you said it has to be run twice. The variable must also be defined each time so a new PID is created for the process.

Right?

Link to comment
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
 Share

  • Recently Browsing   0 members

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