?
Solved

Why is this label not recognized?

Posted on 2014-08-14
22
Medium Priority
?
241 Views
Last Modified: 2014-09-01
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
0
Comment
Question by:aikimark
  • 10
  • 8
  • 4
22 Comments
 
LVL 40

Assisted Solution

by:Subsun
Subsun earned 800 total points
ID: 40262310
I could see Loop label does not work with Foreach-Object, May be because It accepts data from pipeline... You can try replacing it with Foreach loop
:innerloop foreach ($obj in $GHF) {$MV = $obj.Installedon; break :innerloop}

Open in new window

0
 
LVL 46

Author Comment

by:aikimark
ID: 40262391
Both accept stream input.  The Foreach works.  

I do not seek a work-around, but an understanding of this phenomenon.
0
 
LVL 40

Expert Comment

by:Subsun
ID: 40262401
Foreach wont accept pipeline output.. only foreach-object does..
0
Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

 
LVL 46

Author Comment

by:aikimark
ID: 40262406
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.
0
 
LVL 40

Assisted Solution

by:Subsun
Subsun earned 800 total points
ID: 40262435
What you man by 'Not true'? are you saying there is no difference between Foreach-Object and foreach?

As per my knowledge foreach (Which is a looping construct) and ForEach-Object is a cmdlet (It also has alias foreach and %). Difference is that the First one generates the entire collection specified in the pipeline before processing it. On the other hand Foreach-Object gets one object once by one from pipeline and pass in on.

Regarding the label, As per the MS documentation Foreach-Object doesn't support label. See the exerts from following article.
Ref  : http://technet.microsoft.com/en-us/library/hh847873.aspx
The label is a colon followed by a name that you assign. The label must be the first token in a statement, and it must be followed by the looping keyword, such as While.
 
    In Windows PowerShell, only loop keywords, such as Foreach, For, and While can have a label.
0
 
LVL 46

Author Comment

by:aikimark
ID: 40262449
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.
0
 
LVL 40

Expert Comment

by:Subsun
ID: 40262475
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..
0
 
LVL 41

Expert Comment

by:footech
ID: 40263572
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

0
 
LVL 46

Author Comment

by:aikimark
ID: 40263622
@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.
0
 
LVL 41

Assisted Solution

by:footech
footech earned 1200 total points
ID: 40263825
Yes, depending on the surrounding code/syntax, "foreach" could be either the foreach statement or ForEach-Object cmdlet.  There's no way you could type ForEach-Object and have it be the foreach statement though.
foreach (.. in ..){..}  <-always the foreach statement
.. | foreach {..}    <-always the foreach-object cmdlet
Since the break statement only works with looping statements, and not the ForEach-Object cmdlet, that is why a break included in the scriptblock of ForEach-Object would break out of any loop that contained the ForEach-Object construct, or if there wasn't one, would halt execution of the script.

I can pipe the $GHF stream into both of these.
Can you show me?  I think then I could clear up any confusion.  If you mean foreach($g in $GHF){$MV = $g.Installedon; break} - that is not using the pipeline.
0
 
LVL 46

Author Comment

by:aikimark
ID: 40268370
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

0
 
LVL 46

Author Comment

by:aikimark
ID: 40268374
If you want to see this on your system, $GHF = get-hotfix
0
 
LVL 41

Expert Comment

by:footech
ID: 40268418
Both of those are using the ForEach-Object cmdlet, the first one just happens to be using the alias instead of the full name.
0
 
LVL 46

Author Comment

by:aikimark
ID: 40268437
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.
0
 
LVL 41

Expert Comment

by:footech
ID: 40268510
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.
0
 
LVL 41

Expert Comment

by:footech
ID: 40268516
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.
0
 
LVL 46

Author Comment

by:aikimark
ID: 40268589
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.
0
 
LVL 41

Accepted Solution

by:
footech earned 1200 total points
ID: 40268728
Nothing I can point to off-hand.  I think the help for about_foreach is misleading.  In my opinion they should have completely separated the ForEach-Object syntax guidance (i.e. not included it at all in that topic).  The entire section "The Foreach Statement Inside a Command Pipeline" applies to the ForEach-Object cmdlet and should have only been included in the help for that cmdlet.   The difference between foreach and ForEach-Object is a source of confusion for many beginners.  I assume you've also read the help for about_break.
0
 
LVL 46

Author Comment

by:aikimark
ID: 40268734
yes.  It was as fuzzy/nebulous as the foreach description.
0
 
LVL 41

Expert Comment

by:footech
ID: 40268768
I felt it described things pretty well as long as you realize ForEach-Object isn't a looping keyword.
0
 
LVL 41

Expert Comment

by:footech
ID: 40296083
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.
0
 
LVL 46

Author Closing Comment

by:aikimark
ID: 40296425
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.
0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
Windows 10 came with  a lot of built in applications, Some organisations leave them there, some will control them using GPO's. This Article is useful for those who do not want to have any applications in their image (example:me).
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Screencast - Getting to Know the Pipeline

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question