接受位置绑定参数作为参数的函数,也接受来自管道的函数

时间:2017-09-25 16:11:47

标签: powershell pipeline powershell-v5.0

我正在尝试创建一个日志函数,它接受管道位置绑定参数和位置绑定参数。但是,我使用以下代码继续收到此错误:

Function Test
{
[CmdletBinding(SupportsShouldProcess,DefaultParameterSetName='def')]
Param(
  [Parameter(Position=0,ParameterSetName='def')]
  [String]$Pos1,
  [Parameter(ValueFromPipeline,Position=1,ParameterSetName='pip')]
  [String]$InputObject,
  [Parameter(Position=1,ParameterSetName='def')]
  [Parameter(Position=0,ParameterSetName='pip')]
  [String]$State
)
    Process
    {
        Switch ($PScmdlet.ParameterSetName)
        {
            'def' {Write-Host "${State}: $Pos1"}
            'pip' {Write-Host "${State}: $InputObject"}
        }
    }
}

PS C:\> 'this' | Test 'error'

test : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:10
+ 'test' | test 'error'
+          ~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (test:String) [Test], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Test

我可以通过以下示例获取函数的位置绑定管道调用:

Function Test
{
Param(
  [Parameter(Position=1,ValueFromPipeline)]
  [String]$Msg,
  [Parameter(Position=0)]
  [String]$State
)

    Process
    {
        Write-Host "${State}: $Msg"
    }
}

PS C:\> 'this' | Test 'error'
error: this

所以我的问题是:如何创建一个函数,它将在命令行(Test 'message' 'status')和管道('message' | Test 'status')中获取位置绑定参数,而无需显式调用参数名称('message' | Test -State 'status')?

1 个答案:

答案 0 :(得分:2)

让我们用后一个脚本中的以下代码片段替换Process { Write-Host "${State}: $Msg" }块,以获得更具指导性的输出并从中获取信息:

Process
{
    ###  Write-Host "${State}: $Msg"
    Write-Host "State=$State`t Msg=$Msg" -NoNewline
    Write-Host "`t`t`t`t$($MyInvocation.Line.trim())" -ForegroundColor Cyan
}

然后,检查输出(几乎)所有可能的参数组合:

PS D:\PShell> 
'this' | Test    -State 'error'
'this' | Test           'error'
Test -Msg 'this' -State 'error'
Test -Msg 'this'        'error'
Test      'this' -State 'error'
Test      'this'        'error'

State=error  Msg=this               'this' | Test    -State 'error'
State=error  Msg=this               'this' | Test           'error'
State=error  Msg=this               Test -Msg 'this' -State 'error'
State=error  Msg=this               Test -Msg 'this'        'error'
State=error  Msg=this               Test      'this' -State 'error'
State=this   Msg=error              Test      'this'        'error'

PS D:\PShell> 

我们可以看到Test 'this' 'error'的不同输出(没有管道在行中没有明确命名的参数)。因此,Test 'error' 'this'可以提供“正确的”结果。

另一种方法:让我们改变脚本输出,如下所示:

Function Test
{
Param(
  [Parameter(Position=1,ValueFromPipeline)]
  [String]$Msg,
  [Parameter(Position=0)]
  [String]$State
)
    Process
    {
        #Write-Host "${State}: $Msg"
        $auxLine = $MyInvocation.Line.split( ' ', 
                [System.StringSplitOptions]::RemoveEmptyEntries)
        if ( $auxLine[0] -eq $MyInvocation.InvocationName -and
                '-Msg'   -notin $auxLine -and
                '-State' -notin $auxLine ) 
        {
            Write-Host "State=$Msg`t Msg=$State" -NoNewline
            Write-Host "`tALTERED`t`t$($MyInvocation.Line.trim())" -ForegroundColor Yellow
        } else {
            Write-Host "State=$State`t Msg=$Msg" -NoNewline
            Write-Host "`t`t`t`t$($MyInvocation.Line.trim())" -ForegroundColor Cyan
        }
    }
}

<强>输出

PS D:\PShell> 
'this' | Test    -State 'error'
'this' | Test           'error'
Test -Msg 'this' -State 'error'
Test -Msg 'this'        'error'
Test      'this' -State 'error'
Test      'this'        'error'

State=error  Msg=this               'this' | Test    -State 'error'
State=error  Msg=this               'this' | Test           'error'
State=error  Msg=this               Test -Msg 'this' -State 'error'
State=error  Msg=this               Test -Msg 'this'        'error'
State=error  Msg=this               Test      'this' -State 'error'
State=error  Msg=this   ALTERED     Test      'this'        'error'

PS D:\PShell>