Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a Powershell advanced function, how do I detect pipeline input in my BEGIN block?

I have an advanced function

function Start-Executable {
    [CmdletBinding()]
    Param (
        [String]$Arg1,
        [String[]]$Arg2,
        [Parameter(ValueFromPipeline=$true)][String[]]$PipeValue
    )

Begin {
    # Setup code
}
Process {
    # What goes on here?
    foreach ($val in $PipeValue) {
        # Process val here
    }
}
End {
}
}

In my setup code, I need to do something different depending on whether the user supplied pipeline input. But I don't know how I can tell in my BEGIN block if there's pipeline input. Is there something I can check for that?

One other thing I tried was putting the setup code in the PROCESS block, before the loop over $PipeValue, but that doesn't work because it appears that the PROCESS block is called once for each pipeline value, with $PipeValue being an array of one item each time. Is that right? If PROCESS is being called repeatedly for each value, why do I need another loop inside the PROCESS block?

Update

To clarify, what I'm trying to do is create a process in BEGIN, feed it input in PROCESS and read the output in END. For this to work I need to set RedirectStandardInput to $true if there is pipeline input, but not otherwise.

As workarounds, I can either make the user specify with an extra argument (and if they get it wrong, things don't work) or I can set a $first_time flag in BEGIN, then create the process the first time PROCESS is called. If I get to END without having created the process, I create it there with RedirectStandardInput as $false. That's more code duplication than I like, but if it's the only option I may have to do it that way.

like image 715
Paul Moore Avatar asked Dec 01 '22 16:12

Paul Moore


2 Answers

$MyInvocation.ExpectingInput returns true if the function is invoked with pipeline input, and false otherwise.

This works in begin, process, and end blocks. It does not work in dynamicparam in PowerShell 5.1 or lower.

like image 116
Pyprohly Avatar answered Dec 09 '22 17:12

Pyprohly


The Begin block runs before the pipeline is started, so there's no way for that code to know what's in the pipeline.

As far as needing another loop inside the Process block, you have to have that if the function needs to accept whatever $PipeValue is as either pipeline input or passed as a parameter. If it's only going to accept that as pipeline data, then there's no point in having a parameter for it. Just use $_ inside the process block.

like image 30
mjolinor Avatar answered Dec 09 '22 18:12

mjolinor