I'm trying to find some way of flexibly altering/substituting pipeline elements in 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}
Which I want to return the DNs of all the users that report to Colonel Foobar, but it gives me the error Expressions are only allowed as the first element of a pipeline.
This is a trivial example, but I'd ultimately like to be able to put the pipeline step inside a loop and pass it different ScriptBlocks to get different sets of users, or use more complicated ScriptBlocks (e.g.: {Where-IsEmployee | Where-IsInDepartment "Finance" | Where-LikesIceCream}).
I realize that I may be going about this all wrong, and I would very much appreciate being pointed in the right direction.
EDIT: To clarify, here's a rough outline of what I'd like to accomplish:
[ScriptBlock[]] $arrBlocks = @( # lots of different cases
)
ForEach ($sb In $arrBlocks) {
$DNs = $users | $sb | %{$_.DistinguishedName}
# Then do something with the DNs
}
Realistically, this will probably involve a hash table instead of an array, so that I know what to do with each set of results.
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"}}}
You also can't throw $sb into the pipeline quite like that, try this:
$users | &$sb | %{$_.DistinguishedName}
The syntax error is simple:
# Wrong:
$DNs = $users | $sb | %{$_.DistinguishedName}
# Correct; note the call operator in front of $sb:
$DNs = $users | &$sb | %{$_.DistinguishedName}
This still leaves the matter of your pipeline hitting a dead end. You don't need to get fancy here; just pipe $Input along to the next function:
[ScriptBlock] $sb = {$Input | Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}
You shouldn't have $sb itself enumerate the input. That's extra overhead, and if you use param(), bumps the script block up to a cmdlet. You really don't need that.
In fact, you could simplify this whole thing down to four lines, or even one really long line:
$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 }
I tested that with this code:
$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
You could make it a bit more verbose, if you wanted to:
$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 }
You sound like you want to eventually have multiple filters. This is pretty easy, too:
$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 }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With