管道进入 ScriptBlock

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)

实际上,这可能会涉及哈希表而不是数组,以便我知道如何处理每组结果。

Kei*_*ill 5

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)


Zen*_*xer 5

语法错误很简单:

# 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)