Home > Software engineering >  -pipelinevariable and blocking commands in Powershell
-pipelinevariable and blocking commands in Powershell

Time:02-03

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-7.3

“Some blocking commands collect all the pipeline items before producing any output, for example Sort-Object or Select-Object -Last. Any PipelineVariable assigned in a command before such a blocking command always contains the final piped item from the preceding command when used in a command after the blocking command.”

I’m piping an array of AzureADUser objects to Get-EXOMailboxStatistics and it works. But the later is breaking the pipeline. I’m trying to do format-table and use the variable from -pipelinevariable to add a property to the mailboxstat. But it brings the last element. I’m suspecting because it’s blocking and that screws up the element. I can work around this with a foreach loop, but that slows it down by 20 times. Is there a way to avoid that?

Thanks

echo $azureadusers -pipelinevariable user | Get-EXOMailboxStatistics -Properties LastInteractionTime,LastUserActionTime,lastlogontime | format-table @{
     name='UPN’; expression={$user.UserPrincipalName}}, displayname, LastUserActionTime

CodePudding user response:

I have no experience with Get-EXOMailboxStatistics but by what you have already stated in your question, it is consuming all input from the pipeline before outputting hence $user becomes the last element in $azureadusers. In other words, Get-EXOMailboxStatistics is not a streaming cmdlet.

A way to see what this means is by comparing a streaming cmdlet such as ForEach-Object:

Get-Process -PipelineVariable proc | ForEach-Object { $_ } |
    Format-Table @{ N='Name'; E={ $proc.ProcessName }}

With a cmdlet that consumes all input before outputting such as Sort-Object:

Get-Process -PipelineVariable proc | Sort-Object ProcessName |
    Format-Table @{ N='Name'; E={ $proc.ProcessName }}

The workaround in your case is to use a loop of your choice, Foreach-Object in this case:

$azureadusers | ForEach-Object {
    $user = $_
    $user | Get-EXOMailboxStatistics -PropertySets All |
        Select-Object @{ N='UPN'; E={ $user.userprinciplename }}, displayname, LastUserActionTime
} | Format-Table

CodePudding user response:

Faced the same issue as OP, switched to using Get-Mailboxstatistics instead, with that the pipline variable iterates.

echo $azureadusers -pipelinevariable user | Get-MailboxStatistics | format-table @{
     name='UPN’; expression={$user.userprinciplename}}, displayname, LastUserActionTime

  • Related