Pregunta ¿Comportamiento ValueFromPipeline?


Tengo un comando Get-Testdata que recupera datos de prueba de diferentes fuentes y los almacena en un PSObject con los diferentes valores como propiedades. El número total de objetos se almacena como una matriz, para facilitar la manipulación, clasificación, cálculo, etc.

Mi problema es que quiero poder presentar esta información como HTML (codificado por colores), para lo cual escribí otro comando. Show-TestResults. El parámetro de entrada se ve así

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

ACTUALIZACIÓN 1

Esta función en sí misma es muy básica, simplemente establece algunos parámetros para ConvertTo-HTML y luego canalizar los objetos en ese comando:

$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

FINALIZAR ACTUALIZACIÓN 1

Sin embargo, cuando intento usar el ValueFromPipeline propiedad, usando la llamada

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

solo se muestra el primer objeto en la matriz. Pero si, en cambio, llamo al comando como

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

Toda la matriz se presenta, como se esperaba. ¿Alguien puede explicar esto, y espero que me guíe para corregirlo?


11
2018-02-17 13:07


origen


Respuestas:


Probablemente proceses los datos en el bloque final, no en el bloque de proceso.

Mira un ejemplo:

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

9
2018-02-17 13:32



Si el requerimiento es una función avanzada, entonces seguiría el camino propuesto por @stej.

De lo contrario, consideraría esta técnica simple cuando una función acepta la entrada de canalización y de parámetro:

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ótese bien $input en este caso es una variable automática para la entrada de la tubería.


4
2018-02-17 15:16



Creo que el problema es que la tubería está desenrollando su matriz en una secuencia de objetos, y presentándolos a su función uno a la vez, en lugar de como una matriz.

¿Funciona si haces esto?

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

2
2018-02-17 15:16



Me encontré con el mismo problema / pregunta y la forma en que normalmente lo resuelvo es como:

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

Como no creo que sea una buena idea exagerar el variable de entrada automática $.

De todos modos, no he visto una respuesta a la parte de la pregunta: "¿Alguien puede explicar esto?"
Supongo que tiene algo que ver con el Directrices de desarrollo fuertemente alentadas Que estados:

Admite el método ProcessRecord
  Para aceptar todos los registros del cmdlet anterior en la canalización,   su cmdlet debe implementar el método ProcessRecord. Windows   PowerShell llama a este método varias veces, una vez por cada registro   que se envía a su cmdlet.

los ProcessRecord método me parece como una DO# método que supongo es invocado por el process bloquear como en la solución de Stej. Pero esto no explica por qué esto funciona de esta manera para un PSCustomObject matriz y no para, por ejemplo, objetos del sistema, como:

Get-psdrive | Show-Data

O incluso:

@(Get-psdrive) | Show-Data

1
2017-12-31 13:21