好的,据我所知,您正在尝试做什么...您想要获取所有 O365 用户的列表,这些用户的 IsLicensed 属性为 $true,BlockCredential 属性为 $false .在这些用户中,您希望从他们的邮箱对象中提取一些数据; DisplayName、Name、PrimarySMTPAddress 和 CustomAttribute2。
我们有几种方法可以做到这一点。第一个更容易放在 shell 中,但实际运行需要更长的时间。第二个需要一些设置,但很快就能完成。
第一种方法
既然我们从Get-MsolUser 知道我们想要什么的标准是什么,我们将使用管道提取我们想要的东西并将其直接扔到Get-Mailbox。
Get-MsolUser -All | Where-Object {$_.IsLicensed -eq $true -and $_.BlockCredential -eq $false} |
Select-Object UserPrincipalName |
ForEach-Object {Get-Mailbox -Identity $_.UserPrincipalName | Select-Object DisplayName,Name,PrimarySMTPAddress,CustomAttribute2}
O365 PowerShell 不喜欢给我们提供过滤初始查询的方法,所以我们在第二步中处理它,这里...
Where-Object {$_.IsLicensed -eq $true -and $_.BlockCredential -eq $false}
这意味着,对于从Get-MsolUser -All 传入的每个项目,我们只希望那些将属性Islicensed 设置为$true 和BlockCredential 设置为$false 的项目。
现在,就确定要查找的邮箱而言,我们只关心Get-MsolUser 的结果,因此我们将从与我们之前的过滤器匹配的每个对象中获取一个属性。
Select-Object UserPrincipalName
如果您只运行到目前为止的所有内容,您将在您的 shell 中获得一个 UPN 列表,用于我们现在将通过管道传输到 Get-Mailbox 的所有帐户。
继续我们的循环...如果您还没有学习ForEach-Object,它用于针对管道中的每个项目运行一个脚本块({} 之间的所有内容),一次一个。
Get-Mailbox -Identity $_.UserPrincipalName
欢迎来到管道运营商 ($_)。我们之前的Select-Object 正在通过管道提供一组对象,这个占位符变量将在我们处理它们时保存每个对象。由于这些对象都具有UserPrincipalName 属性,因此我们引用该属性以将值传递给Get-Mailbox 的Identity 参数。
侧边栏
这是一个如何工作的简单示例..
PS> 1,2,3 | ForEach-Object {Write-Host $_}
1
2
3
每个项目都沿着管道传递,我们一次写出一个。这与您的标准 foreach 循环非常相似。你可以在this Scripting Guy post了解更多关于它们的区别。
继续……
Select-Object DisplayName,Name,PrimarySMTPAddress,CustomAttribute2
我们用最后一个Select-Object 来总结您想要的信息。然后,您可以在 shell 中查看结果,或者通过管道将结果输入Export-Csv,以便在 Excel 中使用。
现在...由于管道是按顺序工作的,因此会产生一些开销。我们正在运行一个命令,收集结果,然后一次将这些结果传递给下一个命令。当我们到达我们的Get-Mailbox 时,我们实际上为我们收集的每个UPN 运行一次Get-Mailbox。在我的组织中,这大约需要 2.5 分钟,而我们的邮箱不到 500 个。如果您正在处理更大的数字,运行它的时间可能会增长得非常快。
第二种方法
由于第一种方法中的大量处理开销是使用管道,我们可以通过尽可能早和彻底地处理我们的数据收集来消除大部分开销。
$Users = Get-MsolUser -All | Where-Object {$_.IsLicensed -eq $true -and $_.BlockCredential -eq $false} | Select-Object -ExpandProperty UserPrincipalName
$Mailboxes = Get-Mailbox | Select-Object UserPrincipalName,DisplayName,Name,PrimarySMTPAddress,CustomAttribute2
$Results = foreach ($User in $Users) {
$Mailboxes | Where-Object UserPrincipalName -eq $User
}
$Results | Export-Csv myFile.csv
前两行是不言自明的。我们获取我们关心的所有用户帐户信息(仅 UPN),然后我们获取我们关心的所有邮箱属性。
foreach ($User in $Users)
$Users 中的每个条目都将存储在 $User 中,然后我们将在随后的脚本块中使用它(在 {} 中)。
$Mailboxes | Where-Object UserPrincipalName -eq $User
$Mailboxes 中的每个项目都通过管道传输到Where-Object,然后我们检查UserPrincipalName 属性是否等于$User 的当前值。然后,所有匹配项都存储在 $Results 中,可以再次通过管道传输到 Export-Csv 以在 Excel 中工作。
虽然这种方法更难在 shell 中写出,并且需要一些额外的初始设置,但它的运行速度要快得多;我的组织需要 22 秒,而第一种方法需要 2.5 分钟。
我还应该指出,将UserPrincipalName 与邮箱数据集一起使用只是为了帮助确保它们与帐户数据集之间的可靠匹配。如果您不希望它出现在最终结果中,您可以随时将 $Results 传递到另一个 Select-Object 并仅指定您关心的属性。
希望这会有所帮助!