Подтвердить что ты не робот

Поведение ValueFromPipeline?

У меня есть команда 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

END UPDATE 1

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

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

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

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

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

4b9b3361

Ответ 1

Вероятно, вы обрабатываете данные в конечном блоке, а не в блоке процесса.

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

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

Ответ 2

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

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

Ответ 3

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

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

,(Get-Testdata [...]) | Show-TestResults 

Ответ 4

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

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 представляется мне как метод С#, который, как я полагаю, вызывается process как в решении от stej. Но это не объясняет, почему это работает для массива PSCustomObject, а не для, например, системные объекты, например:

Get-psdrive | Show-Data

Или даже:

@(Get-psdrive) | Show-Data