HOWTO: PowerShell Function Return Quirk

Have you ever been using PowerShell, created a function that called another function and then tried to return data from the parent function only to discover that the returned data included more ‘stuff’ than you intended? This quick blog post demonstrates why that is and presents one workaround to prevent it in the future.

Clear-Host

Function Show-OutputMessage
{
    # Note that the only thing this function does is write to the pipeline.  It does NOT return any data.
    Write-output "An important message"
}

Function Run-Function
{
    # Inside a function, we call a sub function that inside that calls write-output. 
    Show-OutputMessage

    # Let's assume this parent function performs some kind of operation that returns a status code.  So the only thing we want to return is the status, ie:
    return "OK"
}

$Status = Run-Function
if($Status -ne "OK") { write-host "It's broken" -ForegroundColor Red } else { write-host "It's working” -ForegroundColor Green }

Consider the code above.  Pay attention to the Run-Function.  Let’s say this function performs some operation and then returns a status code upon completion.  In this example, it is returning “OK”.

You would then expect that the code at the end of the script that captures this return code and then performs and if operation on the result would return “It’s working” since it returned OK.  But it doesn’t.  If we run this code, you know what we get?

image

Why is that?

It turns out that unlike other programming languages, PowerShell returns everything that happens inside a function regardless if you use the return function or not.  So in the example above, we used Write-Output to write a message to the pipeline.  This was then returned along with the “OK” from the parent function resulting in an array of:

[0] “An important Message”

[1] “OK”

This is why the if ($Status –ne “OK”) doesn’t work since it’s trying to compare an object to a string.

So what’s the fix?  You need to ensure that the ONLY thing your function returns is the data that you want.  In this case, we don’t want Show-OutputMessage to be returned so we have to send its output to Null as in:

$null = Show-OutputMessage

Now the only data being returned is your “OK” status so the if statement works as expected.

image

The moral of the story is be very careful with what you add to the pipeline while in a function if you care about the return value since it likely isn’t going to be what you expect it to be.

2 comments

    • Marco Horstmann on August 27, 2020 at 8:37 am
    • Reply

    Thx for this post. After working a whole day on a problem without understanding
    why this happens I was able to explain the behavior because of you post and my
    script is now working. 🙂

    1. That frustrated me for the longest time too. Glad I saved you some heart ache. 🙂

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.