Explain ValueFromPipeline in PowerShell Advanced Functions.

Consider the below example, we have created Advanced function to get the specific process
information like Process Name, Process ID (PID), Start Time, Responding status, etc.
function Get-ProcessInformation{
   [cmdletbinding()]
   param(
      [Parameter(Mandatory=$True)]
      [string[]]$name
   )
   Begin{
      Write-Verbose "Program started"
   }
   Process{
      Write-Verbose "Extracting Process Inforamtion" Get-Process $name | Select Name, ID, StartTime, Responding | ft - AutoSize
   }
   End{
      Write-Verbose "Function ends here"
   }
}
Above is the advanced function example. When we run the above command, it will give us the
Process information about the selected tables.
Output
PS C:\WINDOWS\system32> Get-ProcessInformation -name Chrome
Name    Id       StartTime          Responding
----    --       ---------          ----------
chrome 1284    24-04-2020 21:29:25    True
chrome 1316    24-04-2020 21:29:37    True
chrome 2004    25-04-2020 17:12:40    True
chrome 2676    26-04-2020 10:59:37    True
chrome 3096    24-04-2020 23:39:00    True
chrome 4660    25-04-2020 22:43:34    True
chrome 6040    24-04-2020 21:29:31    True
chrome 6548    26-04-2020 10:59:30    True
chrome 6592    26-04-2020 10:59:39    True
chrome 6644    25-04-2020 16:41:59    True
chrome 6780    26-04-2020 09:53:33    True
chrome 7392    25-04-2020 11:47:22    True
chrome 10540   26-04-2020 10:56:49    True
chrome 11288   24-04-2020 21:33:05    True
chrome 12088   26-04-2020 10:59:48    True
chrome 12100   24-04-2020 21:29:38    True
chrome 13112   26-04-2020 10:59:48    True
chrome 13460   26-04-2020 10:59:45    True
Now we will pass the above-created function as the pipeline output and check if it works?
PS C:\WINDOWS\system32> "Chrome" | Get-ProcessInformation
cmdlet Get-ProcessInformation at command pipeline position 1
Supply values for the following parameters:
name:
Get-ProcessInformation : Cannot bind argument to parameter 'name' because it
is an empty string.
At line:1 char:12
+ "Chrome" | Get-ProcessInformation
+             ~~~~~~~~~~~~~~~~~~~~~~
   + CategoryInfo             : InvalidData: (:) [Get-ProcessInformation], Param eterBindingValidationException
   + FullyQualifiedErrorId    : ParameterArgumentValidationErrorEmptyStringNotAl
lowed,Get-ProcessInformation
This doesn’t work because this function is not compatible to use as the Pipeline input. It doesn’t take the “chrome” as its input and asks for the value of the Name variable because of the Mandatory parameter. We simply need to add ValueFromPipeline() parameter. As we have already used the Mandatory parameter in the function so just need to add one more pipeline parameter as shown below.
function Get-ProcessInformation{
   [cmdletbinding()]
   param(
      [Parameter(Mandatory=$True,ValuefromPipeline=$True)]
      [string[]]$name
   )
   Begin{
      Write-Verbose "Program started"
   }
   Process{
      Write-Verbose "Extracting Process Inforamtion" Get-Process $name | Select Name, ID, StartTime, Responding | ft - AutoSize
   }
   End{
      Write-Verbose "Function ends here"
   }
}
Now, let's check if it works or not.
PS C:\WINDOWS\system32> "Chrome" | Get-ProcessInformation
Name    Id    StartTime          Responding
----    --    ---------          ----------
chrome 1284 24-04-2020 21:29:25    True
chrome 1316 24-04-2020 21:29:37    True
chrome 2004 25-04-2020 17:12:40    True
chrome 2676 26-04-2020 10:59:37    True
chrome 3096 24-04-2020 23:39:00    True
chrome 4660 25-04-2020 22:43:34    True
chrome 6040 24-04-2020 21:29:31    True
chrome 6548 26-04-2020 10:59:30    True
chrome 6592 26-04-2020 10:59:39    True
chrome 6644 25-04-2020 16:41:59    True
chrome 6780 26-04-2020 09:53:33    True
chrome 7392 25-04-2020 11:47:22    True
chrome 10540 26-04-2020 10:56:49   True
chrome 11288 24-04-2020 21:33:05   True
chrome 12088 26-04-2020 10:59:48   True
Yes, it works. Now what if we provide the two existing process names as the input, it will not provide the desired result because the string we declared in the parameter section is not an array, it is a single string variable. We will declare it as the String array now.
function Get-ProcessInformation{
   [cmdletbinding()]
   param(
      [Parameter(Mandatory=$True,ValuefromPipeline=$True)]
      [string[]]$name
   )
   Begin{
      Write-Verbose "Program started"
   }
   Process{
      Write-Verbose "Extracting Process Inforamtion"  Get-Process $name | Select Name, ID, StartTime, Responding | ft - AutoSize
   }
   End{
      Write-Verbose "Function ends here"
   }
}
Check the output now.
PS C:\WINDOWS\system32> "Chrome","SkypeApp" | Get-ProcessInformation
Name    Id    StartTime          Responding
----    --    ---------          ----------
chrome 1284 24-04-2020 21:29:25    True
chrome 1316 24-04-2020 21:29:37    True
chrome 2004 25-04-2020 17:12:40    True
chrome 2676 26-04-2020 10:59:37    True
chrome 3096 24-04-2020 23:39:00    True
chrome 4660 25-04-2020 22:43:34    True
chrome 6040 24-04-2020 21:29:31    True
chrome 6548 26-04-2020 10:59:30    True
chrome 6592 26-04-2020 10:59:39    True
chrome 6644 25-04-2020 16:41:59    True
chrome 6780 26-04-2020 09:53:33    True
Name       Id    StartTime       Responding
----       --    ---------       ----------
SkypeApp 2552 21-04-2020 18:31:02    True
Here, we are getting the desired output but for each new process, we are getting headers and we don’t need that. We need the combined output so we will use the foreach loop here and required to use PSCustomObject to gather the data.
function Get-ProcessInformation{
   [cmdletbinding()]
   param(
      [Parameter(Mandatory=$True,ValuefromPipeline=$True)]
      [string]$name
   )
   Begin{
      Write-Verbose "Program started"
      $out = @()
   }
   Process{
      Write-Verbose "Extracting Process Inforamtion" $procs = Get-Process $name
      foreach($proc in $procs){
      $out += [PSCustomObject]@{
         "Process_Name" = $proc.Name
         "PID" = $proc.Id
         "Start_Time" = $proc.StartTime
         "Responding?" = $proc.Responding
      }
   }
}
   End{
      $out
      Write-Verbose "Function ends here"
   }
}
When you check the output above, the output is combined and as expected.
PS C:\WINDOWS\system32> "Chrome","SkypeApp" | Get-ProcessInformation
Process_Name    PID       Start_Time          Responding?
------------    ---       ----------          -----------
chrome          1284    24-04-2020 21:29:25    True
chrome          1316    24-04-2020 21:29:37    True
chrome          2004    25-04-2020 17:12:40    True
chrome          2676    26-04-2020 10:59:37    True
chrome          3096    24-04-2020 23:39:00    True
chrome          4660    25-04-2020 22:43:34    True
chrome          6040    24-04-2020 21:29:31    True
chrome          6548    26-04-2020 10:59:30    True
chrome          6592    26-04-2020 10:59:39    True
chrome          6644    25-04-2020 16:41:59    True
chrome          6780    26-04-2020 09:53:33    True
chrome          7392    25-04-2020 11:47:22    True
chrome          10540   26-04-2020 10:56:49    True
chrome          11288   24-04-2020 21:33:05    True
chrome          12088   26-04-2020 10:59:48    True
chrome          12100   24-04-2020 21:29:38    True
SkypeApp        2552    21-04-2020 18:31:02    True