PowerShell ArrayList and Pipeline Output

There has been many occasions when I think “I should do this with PowerShell!” or “This is a good reason to learn Powershell!“. Surprisingly, one of the biggest ‘gotchas’ I faced was dealing with “uncaptured” pipeline output contained in functions.

One of the things I’ve learned to love about PowerShell is the ability to create .NET objects when necessary. This was useful for my first use case of consuming REST APIs. Having no idea of the amount of data that would be returned from these APIs I would need something dynamic and a .NET ArrayList would suit my purpose. As the code below demonstrates, creating the ArrayList and using a REST API in PowerShell should be familiar to any .NET developer.

function Get-ApiData
{
$theArray = New-Object System.Collections.ArrayList

$result = Invoke-RestMethod 'https://projects.propublica.org/nonprofits/api/v1/search.json'
foreach($key in $result.filings)
{
    $theArray.Add($key.updated)
}
return $theArray
}

After using the appropriately named “Invoke-RestMethod” to call the REST API and performing some simple parsing to push the interesting data into the ArrayList I was ready to work with it. I assumed the array would be filled with date and time stamps but upon inspection my array contained the following:

debug.output.arraylist.powershell

It looks as if there are extra values in the ArrayList; this was unexpected. As it turns out this is caused by how PowerShell deals with “uncaptured” output to its pipleline. The operation of adding a value to the ArrayList generates output! The following, even simpler, example demonstrates this. Note that this was entered directly into the PowerShell prompt and not contained in a function as seen above.

$theArray = New-Object System.Collections.ArrayList
$theArray.Add("test")

With its output as:

array.output

You can ignore this output by simply redirecting it to $null. $null is an automatic variable in PowerShell that represents…well…and empty value. The workaround for PowerShell to ignore such output can be achieved in a few ways.

$theArray.Add($key.updated) > $null

Or

$theArray.Add($key.updated) | Out-Null

Or

[void]$theArray.Add($key.updated)

My preferred method is the first as its the most similar to output is redirected in *nix shells.

Revising the code from the original example and the output is what I expected.

function Get-ApiData
{
$theArray = New-Object System.Collections.ArrayList

$result = Invoke-RestMethod 'https://projects.propublica.org/nonprofits/api/v1/search.json'
foreach($key in $result.filings)
{
    $theArray.Add($key.updated) > $null
}
return $theArray
}

revised.debug.output

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s