|之间的差异和 $

Differences between | and $

任何人都可以向我解释一下我在使用 | 将一个命令传输到另一个命令或使用 $ 到 'pipe' 的不同方式中看到的差异(抱歉不确定使用 $ 是否真的在考虑管道)。

所以……这有效:

Get-Mailbox -ResultSize Unlimited | 
    where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" } | 
    Get-MailboxPermission

这很好,但是因为我想在 Get-MailboxPermission 之后放置另一个 where 命令,它在上面不起作用我然后尝试使用这个:

$Mailbox = Get-Mailbox -ResultSize Unlimited | 
           where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" }

Get-MailboxStatistics -Identity $Mailbox |
    where { $_.IsInherited.tostring() -eq "False" }

它导致我得到这个错误:

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".

当然使用 |$ 是相同的,因为它将结果通过管道传递给下一个命令,还是我完全错了?

很抱歉不得不这么说,但你完全错了。管道和变量是两个完全不同的东西。

管道 (|) 将一个 cmdlet 的输出连接到另一个 cmdlet 的输入。列表输出一次处理一项,即第二个 cmdlet 分别接收每个列表项。

如果您在变量 ($mailbox) 中收集项目列表并使用该变量调用 cmdlet,则您传递的是列表对象而不是单个列表项目。仅当 cmdlet 参数接受数组输入时才有效。

我这里没有交换 shell 来测试,但我想我仍然可以解释基础知识并为您指明正确的方向。

管道|用于将输出从一个命令重定向到另一个命令。 Powershell 中的 $ 是定义紧随其后的字符序列是变量的字符(例如 $Mailbox 作为普通变量的示例,或者 $_ 作为变量一个变量的示例,该变量保存已从上一个命令通过管道传输的数据)或表达式。一个表达式的例子是 $(4+5).
或者在一个更常用的例子中:

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

在该示例中,实际上有必要使用表达式,因为字符串中的变量检测不会将点识别为变量和变量成员之间的分隔符(fullname 是 [=19= 的成员]).
如果您不清楚为什么有一个点以及成员是什么,您可能应该稍微研究一下面向对象编程,因为 Powershell 是彻头彻尾的面向对象。

在您的第二个示例中,您只需将 Get-Mailbox 命令返回的所有内容保存在 $Mailbox 变量中。 $Mailbox 变量可用,只要您不删除它或离开其范围(在本例中为 powershell 会话)。您实际上可以将变量用作多个命令的输入而不会丢失其数据。
使用管道时,第一个命令返回的数据只能由管道后面的命令访问,之后它就消失了。
这可能是您感兴趣的区别。

至于你的实际问题: Powershell 告诉你它不希望被传递给 System.Collections.ArrayList 类型的变量,这就是 Get-Mailbox returns。 technet 帮助不清楚 Get-Mailbox 具体是什么 returns,但我强烈猜测它是邮箱对象的 ArrayList。你可以这样检查:

$Mailbox.GetType()
$Mailbox[0].GetType() # gets the type of the first object in $Mailbox

要修复您的代码,您需要遍历 Get-Mailbox 返回的内容。试试这个:

$Mailboxes = Get-Mailbox -ResultSize Unlimited | where { $_.RecipientTypeDetails.tostring() -eq "SharedMailbox" }
$Mailboxes | ForEach-Object { Get-MailboxStatistics -Identity $_ }

ForEach-Object cmdlet 遍历数组或列表并单独处理每个项目。
您的第一个示例到目前为止有效,因为 Powershell has been made smarter about piped data a few versions ago(请参阅有关 'Member Enumeration' 的段落)。它实际上是对传入的数据进行 ForEach。

跟进链接:
The $_ variable in powershell
Powershell is an object oriented language

管道运算符|我曾经将一个命令的输出流入另一个命令的输入。

美元符号c,$用于表示其后的名称是一个变量,与cmdlet 之间的管道数据无关。 where cmdlet 创建一个 $_ 变量以在其表达式中使用。