Foreach loop

This topic contains 5 replies, has 3 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 3 years, 2 months ago.

  • Author
    Posts
  • #14847
    Profile photo of
    Anonymous

    Coming from a Python background, how does one accomplish something along the lines of looping through each object returned from a Get-MailBox and Get-MailUser?

    foreach ($user in (Get-MailUser -ResultSize unlimited))
    {..}

    I know how I can stuff both cmdlets in the single collection in the above foreach loop but its so ugly.
    Its a script so I wont use pipes (personal preference, I dont think a pipe belongs anywhere but a shell).

    PowerShell lacks the syntactic sugar that Python has for doing things like this idiomatically. Without pipes, how does one iterate over multiple collections without invoking the retrieval early? Its bad enough this consumes the set before iterating.

    Thanks!

  • #14849
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I'm not sure I understand the question. Are you trying to combine the results of two commands into a single collection?

  • #14851
    Profile photo of Ritmo2k
    Ritmo2k
    Participant

    Hi Dave,
    That is exactly right. Does powershell support such syntax or must it be nested? If so, without pipes how can you process each object returned without consuming the entire result set before iterating?

    Thanks.

  • #14852
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The pipeline is PowerShell's primary means of streaming objects instead of holding an entire result set in memory. If that's your goal, you'll need to stop avoiding the pipeline completely.

    That said, you can put multiple commands into a script block and invoke it like a single command, piping the results to another command (ForEach-Object, or whatever.) This accomplishes what you were trying to do:

    $scriptBlock = {
        Get-MailUser
        Get-MailBox 
    }
    
    & $scriptBlock |
    ForEach-Object {
        # Do something
    }
    
  • #14854
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I'm not sure where that "avoid the pipeline" sound byte came from originally, but it's been taken way out of context. It's important to know when to use the pipeline (essentially, anytime streaming of objects is required.) That said, if you already have a whole collection in memory to begin with, the foreach statement gives much better performance.

    The pipeline is the only way to process items output by a cmdlet one at a time, but it doesn't necessarily mean you're using ForEach-Object. Any command that accepts pipeline input can be used, including your own functions or filters.

  • #14853
    Profile photo of Ritmo2k
    Ritmo2k
    Participant

    That's in a nut shell how I got them in one one foreach loop.

    So, is it not common belief that a pipe should be avoided in a script?
    I am of the thought that they are not typically programmatic approaches but cmdline or shell like operators.

    Is ForEach-Object the only way to process items returned from a cmdlet without consuming the entire result set first?
    If one choose not to use pipes, could you still iterate over the return from say Get-MailBox, one mailbox at a time as they are returned?

    Thanks for the insight Dave!

You must be logged in to reply to this topic.