我正在尝试寻找一些方法来灵活地更改/替换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}我想返回向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
}实际上,这可能会涉及一个哈希表而不是一个数组,这样我就知道如何处理每组结果。
发布于 2013-07-20 05:29:38
在你的scriptblock中需要在管道的头部有一些东西,你必须将你的scriptblock定义为接受管道输入。例如:
[scriptBlock]$sb = {[CmdletBinding()]param([Parameter(ValueFromPipeline=$true)]$obj) `
process {
foreach ($o in $obj) {
$o | Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}}}你也不能像那样把$sb放到管道中,试试这个:
$users | &$sb | %{$_.DistinguishedName}发布于 2013-07-20 11:16:31
语法错误很简单:
# Wrong:
$DNs = $users | $sb | %{$_.DistinguishedName}
# Correct; note the call operator in front of $sb:
$DNs = $users | &$sb | %{$_.DistinguishedName}这仍然会让你的管道陷入死胡同。您不需要在这里花哨;只需将$Input传递到下一个函数:
[ScriptBlock] $sb = {$Input | Where-DirectlyReportsTo "CN=Colonel Foobar,$OU"}你不应该让$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 }我用下面的代码进行了测试:
$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如果你愿意,你可以让它变得更冗长一些:
$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 }你听起来像是想要最终拥有多个过滤器。这也很简单:
$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 }发布于 2013-07-21 07:07:05
在PS2.0中,这在某种程度上更简洁(可读性?)语法是有效的。(在PS 3.0中不起作用,设置isFilter会抛出异常)
$filterSet =
{$_.property -eq "desired value"},
{$_.method() -eq "I like the return value"},
{$_.gettype() -eq [special.type.I.like]},
{arbritraryBoolPSfunction $_}
$filterSet | % {$_.isFilter = $true} # make 'em all filters
ForEach ($filter In $filterSet) {
$DNs = $users | & $filter | %{$_.DistinguishedName}
# Then do something with the DNs
}https://stackoverflow.com/questions/17755504
复制相似问题