$input gotchas

$input (a.k.a. “dollar input” or “input variable”) is one of those esoteric parts of the PowerShell language that create a lot of confusion. In fact just today there was a discussion on how it actually works on the PowerShell MVP mailing list. We even had to read the documentation to figure it out. 😉

Anyways, basically $input in an enumerator which provides access to the pipeline you have.

So basically if you have a function which sums up the elements from the pipeline you can have something like:

Function Sum {
    $sum = 0
    $input |  foreach { $sum += $_ }

1, 2, 3 | Sum

Easy. In fact if you have ever added any script actions or links in the PowerGUI admin console, this is basically what you use to get access to the selection from the central grid.

Now, there are a couple not so obvious gotchas here:

1. Enumerator is not an array

Suppose you want to know how many objects you get from the pipeline – a totally valid question. Maybe your function is supposed to only get one.

You just do $input.Count and… get nothing. Such property does not exist. This is an enumerator and it simply does not have such a property.

OK, you say, let’s wrap it into an array and we’ll learn the size:


This works… Kind of… If you modify our example above to:

Function Sum {
    "Number of elements: " + @($input).Count
    $sum = 0
    $input |  foreach { $sum += $_ }
    "Sum is: " + $sum

1, 2, 3 | Sum

You get:

Number of elements: 3
Sum is: 0

The first line is correct – we had 3 elements. But why the heck is the sum 0 now?

Well, $input is an enumerator, and when you use it – you get to the next element. So once we used it to create a temporary array we got to its end. To fix it, simply reset it back:

Function Sum {
    "Number of elements: " + @($input).Count

    $sum = 0
    $input |  foreach { $sum += $_ }
    "Sum is: " + $sum

1, 2, 3 | Sum

Now we are good again:

Number of elements: 3
Sum is: 6

2. Just using $input holds the pipeline till all objects are collected

This second one was spotted by Per here. He tried using $input and noticed that his function did not get executed until the whole pipeline was processed (that is his function was not invoked for each element one by one, but rather for the whole collection) – read his post for details.

This happens because according to PowerShell help:

“In the Process block of a function, $input contains the object currently in the pipeline… If the function does not have a Process block, the value of $input is available to the End block, and it contains all of the input to the function.”

So basically the reason for the code above to process the whole collection (rather than go item by item) is that we did not have a process block inside the function, so if you care about item by item processing – go with the process block, if not – feel free to use $input.

And by the way, inside the process block just stick to $_ like this:

Function Sum {
  begin { $sum = 0 }
  process { $sum += $_ }
  end { $sum }

1, 2, 3 | Sum

Using $input inside process is a hustle and Oisin promised a post on his blog on the reasons why. 😉

Tags: , , ,

10 Responses to “$input gotchas”

  1. 1 PSLover October 27, 2010 at 11:38 pm

    I will have to say many thanks for providing a google result to this one!!!

  2. 3 Sol February 22, 2012 at 9:18 am

    This saved my bacon, thanks!

  3. 4 Erick Calder September 26, 2013 at 9:00 pm

    something’s wrong with use of this variable when declaring a parameter with ValueFromRemainingArguments… I get an error that “The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input” – thoughts?

  4. 5 copdips September 12, 2015 at 2:09 pm


    Seems that I use Begin/Process/End blocks, @(Input).count doesn’t work any more. What I would like to do is use Begin/Process/End blocks and also use Write-Progress in Process block. That’s why I need @(Input).count to get the total number of the input objects. Could you please help me ? Thx

    • 6 pigeonlips November 29, 2015 at 8:43 pm

      would love to know the answer too this too. All i could find was to add the pipeline item to an array in the process block and then do the work in the end block. Not great

      Function Sum {

      begin {

      $AllTheSum = @()

      } process {

      $AllTheSum += $_

      } end {


      $AllTheSum | ForEach {

      Write-Progress -PercentComplete $Count/$AllTheSum.Count * 100

      # something with $_




  5. 8 Anonymous March 5, 2020 at 1:19 am

    Dead links in “Using $input inside process is a hustle and Oisin promised a post on his blog on the reasons why. 😉”

  6. 9 Rex Bontrager June 8, 2020 at 3:24 pm

    Within the PROCESS block, when objects are slowly dripping in from the pipeline: Is there any way to check if the object is ready to be read from the pipeline? Like:
    If ($Pipeline.DataReady) {$obj = $Pipeline.Read()} else {…}

  1. 1 Vadims Podans's blog - Функции и фильтры в PowerShell Trackback on January 12, 2009 at 7:04 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

My Recent Tweets


The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

November 2008

%d bloggers like this: