≡ Menu

Exchange Management Shell Error: Pipelines Cannot be Executed Concurrently

When working in the Exchange Management Shell in Exchange Server 2010, you may run into the following error:

Pipeline not executed because a pipeline is already executing. Pipelines cannot be executed concurrently.
+ CategoryInfo : OperationStopped: (Microsoft.Power…tHelperRuns
pace:ExecutionCmdletHelperRunspace) [], PSInvalidOperationException
+ FullyQualifiedErrorId : RemotePipelineExecutionFailed

This error is caused when executing the Exchange cmdlets through PowerShell remoting, which do not support more than one pipeline running at the same time. You may see this error when you pipe the output from a cmdlet to foreach-object, which then runs another cmdlet within its scriptblock.

A Simple Example

Although, you may encounter this error running any of the cmdlets, this a typical scenario:

You can see here we are piping the output of Get-Mailbox to foreach-object and attempting to run the Set-Mailbox cmdlet. We’re getting an error trying to set the max send size on all of the mailboxes to 10MB.

The Set-Mailbox cmdlet is designed to accept pipeline input from Get-Mailbox, so there is no need to use foreach-object. You just need to pipe Get-Mailbox to Set-Mailbox:

Get-Mailbox | Set-Mailbox -MaxSendSize 10MB

In this case, we’re able to work around the error easily since these cmdlets are designed to work together. The Set-Mailbox cmdlet gladly accepts pipeline input from the Get-Mailbox cmdlet, so there’s no need to loop through the results using foreach-object.

A Typical Example

Most of the time you’ll probably run into this when working with dissimilar cmdlets. Let’s say we want to create Inbox Rules for all the mailboxes in the Sales OU. Typically, you’d just retrieve all the mailboxes in the Sales OU using the Get-Mailbox cmdlet and pipe the results to the New-InboxRule cmdlet, like so:

[PS] C:\>Get-Mailbox -OrganizationalUnit Sales | ForEach-Object{
>>   New-InboxRule -Name Attach `
>>   -Mailbox $_ `
>>   -HasAttachment $true `
>>   -MarkImportance High
>> }
Pipeline not executed because a pipeline is already executing. 
Pipelines cannot be executed concurrently.
    + CategoryInfo          : OperationStopped: 
(Microsoft.Power...tHelperRunspace:ExecutionCmdletHelperRunspace) [],
    + FullyQualifiedErrorId : RemotePipelineExecutionFailed

From the output, you can see that this this throws a concurrent pipeline error. To workaround the issue in this scenario, it becomes a two step process. First, we need to save the results of the Get-Mailbox cmdlet to a variable. Then we can pipe the variable to foreach-object:

$sales = Get-Mailbox -OrganizationalUnit Sales
$sales | ForEach-Object{
  New-InboxRule -Name Attach `
  -Mailbox $_ `
  -HasAttachment $true `
  -MarkImportance High

Since we’re piping the collection of mailboxes saved in the $sales variable to foreach-object, we’re only executing one pipeline per mailbox at a time.

Bypassing Remoting

Although, not supported, you could load the Exchange snap-in from a machine with the Exchange tools installed and bypass remoting, but I would recommend just fixing the problem by using the syntax shown in the previous example. Keep in mind that this isn’t actually supported and if you load the snap-in and do not use remoting, then RBAC is bypassed and you’ll need the appropriate AD permissions to make changes.

Ok now that I’ve put the disclaimer out there, you can do this by starting a standard PowerShell instance on a machine with the Exchange tools installed and loading the Exchange PSSnapin using the Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 command:

Hope this helps!

12 comments… add one

  • c June 14, 2010, 9:31 am

    i can’t seem to get scripts that worked just fine in e12 to run in e14 because of this remoting stuff. tried your suggestions, but had to resort to adding the snapin for local use… how do i make sure i invoke the non-remoting version of the ems?

  • Mike Pfeiffer June 14, 2010, 11:04 am

    Well, to work around remoting errors you would just load the Exchange snapin in a standard PowerShell console as shown in the post.

    This is often a simple fix, if you want to post the relevant portion of your code the is causing the error I can try to help.

  • c June 14, 2010, 12:35 pm

    thank you!

    i’ve got ~12k contacts that i’d like to enumerate, and then turn of the ’emailaddresspolicyenabled’, set a ‘primarysmtpaddress’ and ‘externalemailaddress’, and modify the ‘alias’ attibutes based on values in other attibutes of each object (like the ‘name’). in e12 i believe i was able to use syntax similar to get-mailcontact | foreach-object {set-mailcontact ;} but now it seems that the ems ps-remoting prevents this. i should probably rewrite my scripts, but i’m not sure where to look for reference material.

  • Mike Pfeiffer June 14, 2010, 1:13 pm

    You can pipe get-mailcontact to set-mailconact without using foreach-object, for example:

    Get-MailContact | Set-MailContact -HiddenFromAddressListsEnabled:$true

    For more complex commands that require foreach-object, store the output of get-mailcontact in a variable and then pipe the variable to foreach-object:

    $contact = get-mailcontact
    $contact | foreach-object {…}

    If you’d like, send me an email via my contact page and we can take a closer look at one of your scripts.

  • Paal Amundsen July 8, 2010, 4:30 am

    Thanks for the insight! Exactly what I needed!

  • Mike Pfeiffer July 8, 2010, 4:53 am

    Excellent, thanks for your comment Paal!

  • Tym July 5, 2012, 3:22 am

    I’ve found that you can “schedule” the cmdlets by putting them in parenthesis. E.g.

    Get-Mailboxserver | ForEach { Get-Mailboxdatabase -Server $_.Identity }

    Will produce the pipline error. However if Get-Mailbox is put into a parenthesis, then it will not. I.e.

    (Get-Mailboxserver) | ForEach { Get-Mailboxdatabase -Server $_.Identity }

    By placing the cmdlet within the parenthesis is the same as your suggestion of capturing the output into a variable – in this case an implicit one that exist only during the execution of the command line.

  • max September 13, 2012, 5:23 am

    Tym, really useful notice, thanks !!!

  • Delson May 14, 2013, 8:30 am

    Thanks Tym,

    just placing the parenthesis works perfectly for me :)

  • hari April 15, 2013, 8:01 pm

    the 2nd workaround of using a variable resolved my issue.

    Thankyou so much :)

  • Johnny August 26, 2013, 3:42 pm

    The parenthesis worked great! Thank you both for these tips.

  • Jason Fare November 13, 2013, 5:21 pm

    Doing it from C# fails with the same error. It works from the console. Even if I defined it in parenthesis when it gets to the second iteration it gives the “Pipelines cannot be run concurrently” error. For example, I’m trying to generate a report and the following works on the first iteration, but the second iteration fails. It all works from the console, but not when doing PSRemoting through C#:
    $MailboxServers = Get-MailboxDatabase | Select-object Server -Unique | sort Server -Descending
    $i = 0
    foreach ($MailboxServer in $MailboxServers)
    (Get-Mailbox -ResultSize Unlimited -Server $MailboxServer.Server -Filter {RecipientTypeDetails -eq “UserMailbox”} | Select-Object Guid, Alias, UserPrincipalName, DisplayName, PrimarySmtpAddress, @{Name=”MBLastLog”;Expression={(Get-MailboxStatistics $_).LastLogonTime}}, @{Name=”ActiveSyncDevices”;Expression={(Get-ActiveSyncDevice -Mailbox $_.PrimarySmtpAddress |Select-Object DeviceAccessState.DeviceAccessState)}}) |ForEach-Object -Verbose -Process { Do stuff here with the results. – I’m outputing to a .CSV to save memory even though the GC isn’t collecting it after each iteration or when the script ends. } }

Leave a Comment