Link to home
Start Free TrialLog in
Avatar of aikimark
aikimarkFlag for United States of America

asked on

Why is this label not recognized?

In the following PS script, the innerloop label is not recognized as a valid part of the language.  What's going on and how do I fix this?
$totaltime=0;$mintime=99999999;$maxtime=0;$count=100;$MV="";
:outerloop for ($i=1; $i -le $count; $i++)
{$starttime=get-date
:innerloop foreach-object -process{$MV = $_.Installedon; break innerloop} -inputobject $GHF;
$TS= New-timespan -Start $starttime;  $thisTime=$ts.TotalMilliseconds; if ($thisTime -lt $mintime){$mintime=$thisTime}; if ($thisTime -gt $maxtime){$maxtime=$thisTime}; $totaltime=$totaltime+$thistime};
"For Each: " + $MV,"`tTotal Time: " + $totaltime + "ms;", "`tMin Time: " + $mintime + "ms;","`tMax Time: " + $maxtime + "ms;", "`tAvg Time: " + $totaltime/$count + "ms"

Open in new window


PS version = 2

===================
edited: corrected typo, caught by footech
SOLUTION
Avatar of SubSun
SubSun
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of aikimark

ASKER

Both accept stream input.  The Foreach works.  

I do not seek a work-around, but an understanding of this phenomenon.
Foreach wont accept pipeline output.. only foreach-object does..
Not true.  This works:
$totaltime=0;$mintime=99999999;$maxtime=0;$count=100;$MV="";
for ($i=1; $i -le $count; $i++)
{$starttime=get-date; 
foreach($g in $GHF){$MV = $g.Installedon; break}; 
$TS= New-timespan -Start $starttime;  
$thisTime=$ts.TotalMilliseconds; 
if ($thisTime -lt $mintime){$mintime=$thisTime}; 
if ($thisTime -gt $maxtime){$maxtime=$thisTime}; 
$totaltime=$totaltime+$thistime}; 
"For Each: " + $MV,"`tTotal Time: " + $totaltime + "ms;", "`tMin Time: " + $mintime + "ms;","`tMax Time: " + $maxtime + "ms;", "`tAvg Time: " + $totaltime/$count + "ms"

Open in new window

Besides...your comment does not address my label question.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
What you man by 'Not true'?
I was referring to your prior comment:
Foreach wont accept pipeline output

Both of these looping statements process streamed data.

=============
only loop keywords, such as
I read that documentation as well.  It isn't clear whether this is a comprehensive list or not.
As per y understanding all loop keywords (Do, Foreach, For, or While.) support label, Foreach-Object is a cmdlet and it doesn't support. I don't have any further comments.. Probably other experts can give you more comprehensive proof..
I don't know if I have anything to add, except to back up what Subsun stated.
The foreach statement (as opposed to the ForEach-Object cmdlet) does not work with the pipeline.  There is nothing in the post http:#a40262406 that uses the pipeline.

foreach, for, do, while, and I think switch (sometimes?) are the only looping statements that I know of.  By the way to break out of a labelled loop, there's no colon in front of the label name used with the break statement.
:innerloop foreach ($a in $b){#do something; break innerloop}
                                                   ^
                                     no colon here ^

Open in new window

@foo

Thanks for catching my typo (now corrected).  I had tried several variations in the syntax and, unfortunately, pasted that one.  According to the documentation, the foreach conditionally becomes a foreach-object (or vice versa).  I can pipe the $GHF stream into both of these.  I've used the flavor of each statement in order to  try and label them, facilitating the break.  What I was getting with the foreach-object is a break out of the outermost looping construct.

I know that I can wrap both statements in a function, but I'm trying to avoid adding that overhead.  I'm giving a presentation next Wednesday at the local PS meetup and the version of the script I posted was the simplest.  It executes the simplest version of the code.  I know that I can execute these individually, outputting the totalmilliseconds values.  However, this introduces unnecessary I/O to the performance test.

I have three other bits of PS script that accomplish the same thing, but they do not require a break.  I want an apples-to-apples comparison of all of these with the least amount of overhead as possible.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here is the simplest form of piping a stream into both the foreach and the foreach-object functions/statements.
PS C:\Users\Mark> $pt=""

_____________________________________________________________________________
PS C:\Users\Mark> $GHF | foreach{$PT = $g.Installedon; break}

_________________________________________________________________________________
PS C:\Users\Mark> $pt

Tuesday, November 20, 2012 12:00:00 AM

_________________________________________________________________________________
PS C:\Users\Mark> $pt=""

_________________________________________________________________________________
PS C:\Users\Mark> $GHF | foreach-object -process{$PT = $g.Installedon; break}

_________________________________________________________________________________
PS C:\Users\Mark> $pt

Tuesday, November 20, 2012 12:00:00 AM

Open in new window

If you want to see this on your system, $GHF = get-hotfix
Both of those are using the ForEach-Object cmdlet, the first one just happens to be using the alias instead of the full name.
I assumed that to be the case from the documentation.

As you see, I can break out of these.  The problem comes in when I am trying to execute these nested under an iterator for construct.  The break kills both loops and a label seemed to be the only way to only break out of the inner loop.
In those cases (where there isn't a looping statement), the break statement isn't really halting the ForEach-Object processing, it is halting execution of the entire script/command.
You just need to get away from the idea that ForEach-Object is a loop, even though it does many of the same things.  Thus it is transparent to any type of break statement.
Thanks, foo.  Can you point me to the PS documentation or article/blog about that?

Time is running out on my prep for the Wednesday night PS meetup presentation, so I have to 'let go' of my attempt to compare statements this way.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
yes.  It was as fuzzy/nebulous as the foreach description.
I felt it described things pretty well as long as you realize ForEach-Object isn't a looping keyword.
I think we've pretty well covered all the topics in this question.  It's probably a good idea to go ahead and close it.
The PS presentation went well.  Thanks for your help in my construction of the code for the presentation.

I will add for future readers that the ForEach is an alias for Foreach-object in certain circumstances.