【问题标题】:Function that accepts position-bound parameters as arguments, but also from pipeline接受位置绑定参数作为参数的函数,但也来自管道
【发布时间】:2018-03-06 16:29:41
【问题描述】:

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

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' )?

【问题讨论】:

  • 从管道中移除 ParameterSetName,移除 ParameterSetName='pip'
  • @ArcSet 这样做会导致位置 0 参数被绑定两次,同时绑定到 $InputObject$State,但它确实停止向我抛出错误。

标签: powershell pipeline powershell-5.0


【解决方案1】:

让我们用后面脚本中的以下代码 sn-p 替换 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> 

【讨论】:

  • 只是为了理解这一点,您基本上是在检查非管道输入以获取隐式的、位置传递的参数并基于此翻转输出?很好地使用$MyInvocation
  • 比我希望的要多一点(参数集还有很多不足之处),但它确实有效。谢谢
猜你喜欢
  • 1970-01-01
  • 2015-02-18
  • 2013-11-19
  • 2014-08-23
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 2016-07-06
相关资源
最近更新 更多