Reputation: 196
Can anyone explain to me the differences I'm seeing in either using a |
to pipe one command to another or using $
to 'pipe' it a different way (sorry not sure if the use $
is actually considering piping).
So… this works:
Get-Mailbox -ResultSize Unlimited |
where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" } |
Get-MailboxPermission
Which is great, however because I want to place another where command after the Get-MailboxPermission
which doesn't work above I then tried to use this:
$Mailbox = Get-Mailbox -ResultSize Unlimited |
where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" }
Get-MailboxStatistics -Identity $Mailbox |
where { $_.IsInherited.tostring() -eq "False" }
It causes me to get this error:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "System.Collections.ArrayList" value of type "System.Collections.ArrayList" to type "Microsoft.Exchange.Configuration.Tasks.GeneralMailboxOrMailUserIdParameter".
Surely using |
or $
is the same in the sense that it pipes through the results to the next command or am I completely wrong?
Upvotes: 2
Views: 566
Reputation: 19450
I don't have an exchange shell here to test but I guess I can still explain the basics and point you in the right direction.
The pipe |
is used to redirect output from one command to another command. $
in Powershell is the character which defines that the character sequence right behind it is either a variable (e.g. $Mailbox
as an example for a normal variable or $_
as an example for a variable that holds data that has been piped through from a previous command) or an expression. An example for an expression one is $(4+5)
.
Or in a more frequently used example:
PS C:\Users\Administrator> $file = (get-childitem)[0]
PS C:\Users\Administrator> write-output "The fullname of $file is $($file.fullname)"
The fullname of .ssh is C:\Users\Administrator\.ssh
In that example it is actually necessary to use an expression, because variable detection inside a string doesn't recognize dots as separator between variable and a variable member (fullname
is a member of $file
).
If it's not clear to you why there is a point and what members are, you should probably look into object oriented programming a bit because Powershell is object oriented through and through.
In your 2nd example you just save everything that's returned by your Get-Mailbox
command in the $Mailbox
variable. The $Mailbox
variable is available as long as you don't delete it or leave its scope (in this case, the powershell session). You can actually use the variable as input for multiple commands without losing its data.
When using the pipe, the data returned by your first command is only accessible for the command behind the pipe and after that it's gone.
That's probably the difference you're interested in.
As for your actual problem: Powershell tells you that it's not expecting to be handed a variable of type System.Collections.ArrayList
, which is what Get-Mailbox
returns. The technet help is unclear as to what Get-Mailbox
specificly returns, but I strongly guess it's an ArrayList of Mailbox-Objects. You can check it like this:
$Mailbox.GetType()
$Mailbox[0].GetType() # gets the type of the first object in $Mailbox
To fix your code, you need to loop over what's been returned by Get-Mailbox
. Try this:
$Mailboxes = Get-Mailbox -ResultSize Unlimited | where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" }
$Mailboxes | ForEach-Object { Get-MailboxStatistics -Identity $_ }
The ForEach-Object
cmdlet loops over an array or a list and works on each item individually.
Your first example works so far because Powershell has been made smarter about piped data a few versions ago (See paragraph about 'Member Enumeration'). It's actually ForEach-ing over the passed in data.
Follow up links:
The $_ variable in powershell
Powershell is an object oriented language
Upvotes: 5
Reputation: 62472
The pipe operator |
i used to flow the output of one command into the input of another command.
The dollar symbolc, $
is used to denote that the name following it is a variable, and has nothing to do with piping data between cmdlets. The where
cmdlet create a $_
variable for use within its expression.
Upvotes: 2
Reputation: 200273
Sorry to have to say this, but you're completely wrong. Pipelines and variables are two entirely different things.
The pipe (|
) connects the output of one cmdlet to the input of another cmdlet. List output is processed one item at a time, i.e. the second cmdlet receives each list item separately.
If you collect a list of items in a variable ($mailbox
) and call a cmdlet with that variable you're passing the list object instead of individual list items. That only works if the cmdlet parameter accepts array input.
Upvotes: 3