Обработка конвейера и ввод параметров в функции Powershell - PullRequest
6 голосов
/ 07 марта 2012

Я запутался в том, что увидел в книге «Изучай 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 мне бы хотелось возиться с первым шаблоном, когда второй шаблон намного чище.

Любое понимание будет оценено.

Спасибо.

Ответы [ 5 ]

3 голосов
/ 07 марта 2012

Если вы хотите обработать конвейерный ввод в вашей функции, но не хотите добавлять все атрибуты параметра или хотите обратную совместимость, используйте cmdletbinding меньше.

Если вы хотите использовать дополнительныефункции командлетов сценариев PowerShell, такие как атрибуты параметров, наборы параметров и т. д., а затем переходите ко второму.

2 голосов
/ 20 июля 2013

Нет, первый пример не просто наследие.Чтобы создать функцию 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" }
}

results ...

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 не имел данных, функция прошла проверку синтаксиса.

2 голосов
/ 09 августа 2012

Если кто-то желает получить очень-очень простое объяснение того, как читать из канального ввода, см.

Как написать функцию powershell, которая читает из канального ввода?

Если бы у меня возник этот вопрос, если бы у меня был этот вопрос, я бы сэкономил много времени, потому что этот поток довольно сложный и фактически не объясняет, как обрабатывать конвейерный ввод в функцию.

1 голос
/ 07 марта 2012

Чтобы ответить на ваш вопрос, я бы сказал, что первый шаблон - это просто наследие от PowerShell 1.0, вы также можете использовать $input в классических функциях без блока сценария Process. Поскольку вы только пишете код для PowerShell 2.0, вы можете забыть его.

Что касается функций конвейера, в PowerShell V1.0 они могут обрабатываться с помощью filters.

вам просто нужно знать, что это было сделано так, когда вы берете образцы из сети или когда вам нужно отлаживать старый код Powerhell.

Лично я все еще использую старые functions и filters внутри своих модулей. Я резервирую cmdletbinding для функций экспорта или функций профиля.

Powershell немного похож на лего-блоки, вы можете делать много разных вещей разными способами.

0 голосов
/ 07 марта 2012

Первая форма ожидает одно или несколько имен компьютеров в качестве строковых аргументов либо из списка аргументов, либо из конвейера.

Вторая форма ожидает либо массив строковых аргументов из списка аргументов, либо входные объекты из конвейера, которые имеют имена компьютеров в качестве свойства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...