Using–Filter, Select-Object, ForEach-Object in C# – Exchange PowerShell Automation
Have you ever tried migrating Exchange PowerShell script to be used from C# code? I needed to convert the following script to C#
Get-Mailbox -filter {ResourceType -ne "Room"}| Select-object Alias,DistinguishedName,Identity | foreach-object {Get-MailboxFolderStatistics $_.Alias}
If you run the above script in Exchange 2010 Management Shell you might get the following error message:
Pipeline not executed because a pipeline is already executing. Pipelines cannot be executed concurrently.
+ CategoryInfo : OperationStopped: (Microsoft.Power...tHelperRunspace:ExecutionCmdletHelperRunspace) [],
PSInvalidOperationException
+ FullyQualifiedErrorId : RemotePipelineExecutionFailed
This error is caused because the Windows PowerShell remoting feature doesn't support more than one pipeline running at the same time. To resolve this issue, store the output of the cmdlet earlier in the pipeline in a variable, and then pipe the data stored in the variable to the ForEach cmdlet as shown below:
$Mailboxes = Get-Mailbox -filter {ResourceType -ne "Room"}| Select-object Alias,DistinguishedName, Identity
$Mailboxes | foreach-object {Get-MailboxFolderStatistics $_.Identity}
Now, to get the code working in C#. How do I use the Filter ? How do I use the Select-Object ? How do I store the intermediate result and then pass it into the ForEach-Object? The below code snippet shows how this can be done. I you need a full example of using Exchange PowerShell from C#, you can find it here .
//TODO: Create and Open Runspace, Create and Import Session
//Create a pipline
Pipeline pipe = runspace.CreatePipeline(); //Add the first command Get-Mailbox with the filters
Command CommandGetMailbox = new Command("Get-Mailbox");
CommandGetMailbox.Parameters.Add("Filter", "ResourceType -ne \"Room\"");
pipe.Commands.Add(CommandGetMailbox); // Do a Select-Object on the fields
var props = new string[] { "Alias", "DistinguishedName", "Identity"};
Command CommandSelect = new Command("Select-Object");
CommandSelect.Parameters.Add("Property", props);
pipe.Commands.Add(CommandSelect); //Invoke the First Pipeline and get the results
resultMailboxes = pipe.Invoke(); // Create a second Pipeline..
Pipeline pipe2 = runspace.CreatePipeline(); // Do a write-output of the results so that it can be piped to the foreach
Command Command1 = new Command("write-output");
Command1.Parameters.Add("InputObject", resultMailboxes);
pipe2.Commands.Add(Command1); //Pipe into the ForEach
Command CommandForEach = new Command("ForEach-Object");
CommandForEach.Parameters.Add("Process", ScriptBlock.Create("Get-MailboxFolderStatistics -Identity $_.Identity"));
pipe2.Commands.Add(CommandForEach); //Invoke the second Pipeline..
resultMailboxes = pipe2.Invoke();
//TODO: Display the results and clean up
Enjoy!