aml*_*ssb 2 powershell pipe scriptblock
我试图在 PowerShell 中找到一些灵活更改/替换管道元素的方法:
Function Where-DirectlyReportsTo {
Param (
[Parameter(
ValueFromPipeline = $true,
HelpMessage = "The ADUser object to be tested"
)]
[Microsoft.ActiveDirectory.Management.ADUser] $ADUser,
[Parameter(
Mandatory = $true,
ValueFromPipeline = $false,
Position = 0
)]
[String] $mgrDN
)
Process {
If ($ADUser) {
If ($ADUser.Manager -eq $mgrDN) { Return $ADUser }
}
}
}
$Properties = @("Manager")
$users = Get-ADUser -Filter * -SearchBase $OU -Properties $Properties
[ScriptBlock] $sb = {Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}
$DNs = $users | $sb | %{$_.DistinguishedName}
Run Code Online (Sandbox Code Playgroud)
我想返回向 Foobar 上校报告的所有用户的 DN,但它给了我错误 Expressions are only allowed as the first element of a pipeline.
这是一个微不足道的例子,但我最终希望能够将管道步骤放在一个循环中,并将不同的 ScriptBlocks 传递给它以获得不同的用户集,或者使用更复杂的 ScriptBlocks(例如:){Where-IsEmployee | Where-IsInDepartment "Finance" | Where-LikesIceCream}。
我意识到我可能做错了这一切,我非常感谢被指出正确的方向。
编辑:为了澄清,这里是我想要完成的粗略概述:
[ScriptBlock[]] $arrBlocks = @( # lots of different cases
)
ForEach ($sb In $arrBlocks) {
$DNs = $users | $sb | %{$_.DistinguishedName}
# Then do something with the DNs
}
Run Code Online (Sandbox Code Playgroud)
实际上,这可能会涉及哈希表而不是数组,以便我知道如何处理每组结果。
There needs to be something at the head of the pipeline in your scriptblock and you have to define your scriptblock as taking pipeline input.g.:
[scriptBlock]$sb = {[CmdletBinding()]param([Parameter(ValueFromPipeline=$true)]$obj) `
process {
foreach ($o in $obj) {
$o | Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}}}
Run Code Online (Sandbox Code Playgroud)
You also can't throw $sb into the pipeline quite like that, try this:
$users | &$sb | %{$_.DistinguishedName}
Run Code Online (Sandbox Code Playgroud)
语法错误很简单:
# Wrong:
$DNs = $users | $sb | %{$_.DistinguishedName}
# Correct; note the call operator in front of $sb:
$DNs = $users | &$sb | %{$_.DistinguishedName}
Run Code Online (Sandbox Code Playgroud)
这仍然会使您的管道陷入死胡同。你不需要在这里花哨;只需管道$Input到下一个功能:
[ScriptBlock] $sb = {$Input | Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}
Run Code Online (Sandbox Code Playgroud)
你不应该$sb自己枚举输入。这是额外的开销,如果您使用param(),则会将脚本块提升为 cmdlet。你真的不需要那个。
事实上,你可以将整个事情简化为四行,甚至是很长的一行:
$properties = @("Manager")
$managers = @(
"CN=Colonel Foobar,$OU"
"CN=Sergeant Foobar,$OU"
"CN=Random Manager,$OU"
)
$users = Get-ADUser -Filter * -SearchBase $OU -Properties $properties
$DNs = $users | ?{ $managers -contains $_.Manager } | %{ $_.DistinguishedName }
Run Code Online (Sandbox Code Playgroud)
我用这个代码测试过:
$OU = 'OU=test'
$users = @(
@{
Manager = "CN=Colonel Foobar,$OU";
DistinguishedName = "Show me!"
}
@{
Manager = "CN=Anon Y Mous,$OU";
DistinguishedName = "Don't show me!"
}
'rabbit'
42
$null
@{
DistinguishedName = "Don't show me, either!"
}
@{
Manager = "CN=Random Manager,$OU";
DistinguishedName = "Show me, too!"
}
)
$managers = @(
"CN=Colonel Foobar,$OU"
"CN=Sergeant Foobar,$OU"
"CN=Random Manager,$OU"
)
$DNs = $users | ?{ $managers -contains $_.Manager } | %{ $_.DistinguishedName }
$DNs | Write-Host
Run Code Online (Sandbox Code Playgroud)
如果你想,你可以让它更详细一点:
$properties = @("Manager")
$managers = @(
"CN=Colonel Foobar,$OU"
"CN=Sergeant Foobar,$OU"
"CN=Random Manager,$OU"
)
$filter = { $managers -eq $_.Manager }
$selector = { $_.DistinguishedName }
$users = Get-ADUser -Filter * -SearchBase $OU -Properties $properties
$DNs = $users | ?{ &$filter } | %{ &$selector }
Run Code Online (Sandbox Code Playgroud)
您听起来像是希望最终拥有多个过滤器。这也很简单:
$properties = @("Manager")
$managers = @(
"CN=Colonel Foobar,$OU"
"CN=Sergeant Foobar,$OU"
"CN=Random Manager,$OU"
)
$filters = @(
{ $managers -contains $_.Manager }
{ ![string]::IsNullOrWhiteSpace($_.DistinguishedName) }
)
$selector = { $_.DistinguishedName }
$users = Get-ADUser -Filter * -SearchBase $OU -Properties $properties
$DNs = $users | ?{ $filters.Invoke() -notcontains $false } | %{ &$selector }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6141 次 |
| 最近记录: |