Поведение ValueFromPipeline? - PullRequest
11 голосов
/ 17 февраля 2012

У меня есть команда Get-Testdata, которая извлекает тестовые данные из разных источников и сохраняет их в PSObject с различными значениями в качестве свойств. Общее количество объектов затем сохраняется в виде массива для удобства манипулирования, сортировки, расчета и т. Д.

Моя проблема в том, что я хочу иметь возможность представлять эти данные в виде (с цветовой кодировкой) HTML, для которого я написал другую команду, Show-TestResults. Входной параметр выглядит следующим образом

[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]
[PSObject[]]$InputObject

ОБНОВЛЕНИЕ 1

Эта функция сама по себе очень простая, она просто устанавливает некоторые параметры для ConvertTo-HTML и затем передает объекты в эту команду:

$head = "<style>[...]" #styling with javascript etc
$header = "<H1>Test Results</H1>
$title = "Test results"
$InputObject | ConvertTo-HTML -head $head -body $header -title $title | Out-File $Filename

КОНЕЦ ОБНОВЛЕНИЯ 1

Однако, когда я пытаюсь использовать свойство ValueFromPipeline, используя вызов

Get-Testdata [...] | Show-TestResults 

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

$td = Get-Testdata [...]
Show-TestResults $td 

Весь массив представлен, как и ожидалось. Может кто-нибудь объяснить это - и, надеюсь, поможет мне исправить это?

Ответы [ 4 ]

10 голосов
/ 17 февраля 2012

Возможно, вы обрабатываете данные в конечном блоке, а не в блоке обработки.

Посмотрите на пример:

function getdata {
    1
    2
    3
    4
}
function show-data {
    param(
        [Parameter(mandatory=$true, ValueFromPipeline=$true)]$InputObject,
        [Parameter(mandatory=$true)]$FileName
    )

    # this is process block that is probably missing in your code
    begin { $objects = @() }
    process { $objects += $InputObject }
    end {
        $head = "<style></style>"
        $header = "<H1>Test Results</H1>"
        $title = "Test results"
        $objects | ConvertTo-HTML -head $head -body $header -title $title | Out-File $Filename
    }
}

getdata | show-data -file d:\temp\test.html
4 голосов
/ 17 февраля 2012

Если требуется расширенная функция, я бы пошел по пути, предложенному @ stej.

В противном случае я бы рассмотрел эту простую технику, когда функция принимает и конвейер, и ввод параметров:

function Show-Data
(
    $FileName,
    $InputObject
)
{
    # this is the trick:
    if ($InputObject) { $input = $InputObject }

    # process the input (from pipeline or parameter)
    $input | ConvertTo-HTML > $FileName
}

# pipe data
Get-ChildItem | Show-Data Test1.htm

# pass via parameter
Show-Data Test2.htm (Get-ChildItem)

NB $input в этом случае является автоматической переменной для ввода конвейера.

2 голосов
/ 31 декабря 2017

Я столкнулся с той же проблемой / вопросом, и способ, которым я обычно решаю это, выглядит так:

Function Show-Data {
    param(
        [Parameter(mandatory=$true, ValueFromPipeline=$true)]$InputObject,
        [Parameter(mandatory=$true)]$FileName
    )
    $PipeLine = $Input | ForEach {$_}; If ($PipeLine) {$InputObject = $PipeLine}
    ...

Поскольку я не думаю, что это * хорошая идея перезаписать автоматический $ Input переменная .

Во всяком случае, я не видел ответа на часть вопроса: " Может кто-нибудь объяснить это? "
Я полагаю, что это как-то связано с Руководством по развитию , где говорится:

Поддержка метода ProcessRecord
Чтобы принять все записи из предыдущего командлета в конвейере, Ваш командлет должен реализовывать метод ProcessRecord. Windows PowerShell вызывает этот метод несколько раз, по одному разу для каждой записи отправляется на ваш командлет.

Метод ProcessRecord представляется мне как метод C # , который, как я полагаю, вызывается блоком process, как в решении из stej, Но это не объясняет, почему это работает таким образом для массива PSCustomObject, а не, например, для системные объекты, такие как:

Get-psdrive | Show-Data

Или даже:

@(Get-psdrive) | Show-Data
2 голосов
/ 17 февраля 2012

Мне кажется, проблема в том, что конвейер разворачивает ваш массив в поток объектов и представляет их вашей функции по одному, а не в виде массива.

Работает ли это, если вы сделаете это:

,(Get-Testdata [...]) | Show-TestResults 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...