繁体   English   中英

在Powershell函数中处理管道和参数输入

[英]Handling pipeline and parameter input in a Powershell function

我对在一个月的午餐中学习PowerShell一书中看到的东西感到困惑。 在第21章中,当作者讨论通过参数绑定或管道接受输入的函数时,他给出了两种模式。

第一个如下

function someworkerfunction {
# do some work
}
function Get-SomeWork {
   param ([string[]]$computername)
   BEGIN {
      $usedParameter = $False
      if($PSBoundParameters.ContainsKey('computername')) {
         $usedParameter = $True
      }   
   }
   PROCESS {
      if($usedParameter) {
         foreach($computer in $computername) {
            someworkerfunction -computername $comptuer
         }
      } else {
         someworkerfunction -comptuername $_
      }
   }

   END {}
}

第二个是这样的

function someworkerfunction {
# do stuff
}
function Get-Work {
   [CmdletBinding()]
   param(
      [Parameter(Mandatory=$True,
      ValueFromPipelineByPropertyName=$True)]
      [Alias('host')]
      [string[]]$computername
   )
   BEGIN {}
   PROCESS {
      foreach($computer in $computername) {
         someworkerfunction -comptuername $computer
      }
   }
   END {}
}

我知道第二个样本是标准的Powershell 2.0 Advanced功能。 我的问题是Powershell 2.0对cmdletbinding指令的支持你是否想要使用第一个模式。 这只是Powershell 1.0的遗产吗? 基本上有一段时间使用Powershell 2.0我想要第一个模式,第二个模式更清洁。

任何见解将不胜感激。

谢谢。

如果要在函数中处理管道输入但不想添加所有参数属性或想要向后兼容,请使用cmdletbinding less方法。

如果要使用PowerShell脚本cmdlet的其他功能(如参数属性,参数集等),请使用第二个功能。

如果有人希望对如何从管道输入读取的非常非常简单的解释看到

你如何编写一个从管道输入中读取的powershell函数?

如果我有这个问题时存在这个^ ,我会节省很多时间,因为这个线程非常复杂,并没有真正解释如何处理流水线输入到函数中。

不,第一个例子不仅仅是遗产。 为了创建一个使用数组参数并接受管道输入的PowerShell函数,您必须做一些工作。

我甚至会说第二个例子不起作用。 至少我无法让它发挥作用。

以这个例子为例......

function PipelineMadness()
{
   [cmdletbinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [int[]] $InputArray
    )

    Write-Host ('$InputArray.Count {0}' -f $InputArray.Count)
    Write-Host $InputArray

    Write-Host ('$input.Count {0}' -f $input.Count)
    Write-Host $input

    if($input) { Write-Host "input is true" }
    else { Write-Host "input is false" }
}

结果......

PS C:\Windows\system32> 1..5 | PipelineMadness
$InputArray.Count 1
5
$input.Count 5
1 2 3 4 5
input is true

PS C:\Windows\system32> PipelineMadness (1..5)
$InputArray.Count 5
1 2 3 4 5
$input.Count 1

input is false

请注意,当使用管道时, $InputArray变量的单个值为5 ...

现在使用BEGIN和PROCESS块

function PipelineMadnessProcess()
{
    [cmdletbinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [int[]] $InputArray
    )

    BEGIN
    {
        Write-Host 'BEGIN'
        Write-Host ('$InputArray.Count {0}' -f $InputArray.Count)
        Write-Host $InputArray

        Write-Host ('$input.Count {0}' -f $input.Count)
        Write-Host $input

        if($input) { Write-Host "input is true" }
        else { Write-Host "input is false" }
    }

    PROCESS
    {
        Write-Host 'PROCESS'
        Write-Host ('$InputArray.Count {0}' -f $InputArray.Count)
        Write-Host $InputArray

        Write-Host ('$input.Count {0}' -f $input.Count)
        Write-Host $input

        if($input) { Write-Host "input is true" }
        else { Write-Host "input is false" }
    }
}

现在这是奇怪的地方

PS C:\Windows\system32> 1..5 | PipelineMadnessProcess
BEGIN
$InputArray.Count 0

$input.Count 0

input is false
PROCESS
$InputArray.Count 1
1
$input.Count 1
1
input is true
PROCESS
$InputArray.Count 1
2
$input.Count 1
2
input is true

...

PROCESS
$InputArray.Count 1
5
$input.Count 1
5
input is true

BEGIN块根本没有任何数据。 并且进程块运行良好,但是如果你有一个类似于示例的foreach它实际上可以工作,但它将运行foreach ,1次输入X次。 或者,如果您传入数组,它将使用完整集运行foreach一次。

所以我从技术上说这个例子可行,但它可能不会像你期望的那样工作。

另请注意,即使BEGIN块没有数据,该函数也会通​​过语法验证。

要回答你的问题,我会说第一个模式只是来自PowerShell 1.0的遗产,你也可以在没有Process脚本块的经典函数中使用$input 至于你只是为PowerShell 2.0编写代码,你可以忘记它。

关于管道功能,在powerShell V1.0中,可以使用filters处理它们。

你必须知道,当你从网上采集样本或者你必须调试旧的Powerhell代码时,它已经完成了。

我个人仍然在我的模块中使用旧functionsfilters我保留cmdletbinding用于导出函数或配置文件函数。

Powershell有点像乐高积木,你可以用很多不同的方式做很多事情。

第一种形式是将一个或多个计算机名称作为参数列表或管道的字符串参数。

第二种形式是期望来自参数列表的字符串参数数组,或者来自管道的具有计算机名称作为属性的输入对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM