powershell - 接受位置绑定(bind)参数作为参数的函数,但也来自管道

标签 powershell pipeline powershell-5.0

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

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

我可以获得函数的位置绑定(bind)管道调用以使用以下示例:

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' | 测试 'status') 而无需显式调用参数名称 ('message' | Test -State 'status')?

最佳答案

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

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> 

关于powershell - 接受位置绑定(bind)参数作为参数的函数,但也来自管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46409681/

相关文章:

powershell - 我可以使用系统帐户调用Invoke-RestMethod吗?

c# - cmdlet 写入控制台而不写入管道

python - 在使用 scikit-learn 在 Pipeline 中拟合 ML 模型后,如何将准确度与 Score() 函数中的另一个性能指标交换?

mips - MIPS 中的停顿或气泡

powershell,如何获取 firefox 窗口标题并关闭其中一个

Powershell:如何安装 cmdlet?

powershell - 在变量Powershell中传递参数

powershell - ArrayList .Add 与 .AddRange 对比管道

powershell - 跨多个卷搜索文件

powershell - 通过组合foreach,begin,process和replace命令的Powershell5 Compact代码