Function Return Values

So you are debugging a script what do you do?

  1. Put break points in the script
  2. Echo stuff to the screen
  3. Write a log file – you’re doing this already though aren’t you?
  4. Watch the variable values in the ISE

If you apply the same principles to Functions you might just fall foul of the issues discussed on Keith Hills blog

PowerShell Functions return anything you didn’t capture.  So if you write something to screen by say using the variable name, you just added this to the function output and worse it was not displayed on screen it vanished somewhere.  Actually it didn’t vanish it just got returned by the function.  If you set a variable using $variableName = Get-MyFunction then the variable type will be an array and one of the elements will be the output you expected to go to screen.

Make sure you use write-host to display stuff on screen otherwise you are making things worse not better. In some instances you can’t just echo the value to the screen you will need to write code just to parse the value held in the variable and write them to screen. The alternative is to put a break point in and then type the variable name at the cmd prompt – or use the ISE to view the variable values.

When writing big functions I often build a “test rig” around them and check the return values are as expected.  This means I can feed my function test values and objects and confirm it behaves as expected.    If you are writing production scripts that will run unattended you have to write twice as much code just to deal with error handling.  In functions this is even more critical because  if something unexpected happens and you don’t handle the error then the main script will likely fail because the function returned multiple objects rather than the expected single value.

If you want to be ultra cautious you could check the return value is as expected.  To use Keith Hills’ example you can examine what’s returned like this:

function LongNumericString {
 $strBld = new-object System.Text.StringBuilder
 for ($i=0; $i -lt 20; $i++) {
  $strBld.Append($i)
 }
 $strBld.ToString()
}

$index = 0
LongNumericString | ForEach-Object { Write-Host "Return Object $index type = $($_.gettype().name)" ; $index++  }

From that output you would see that you have an array with lots of objects when you were expecting a single string to be returned.  Once you have that you can make your script fail gracefully.  Why fail?  Because if the output is not as expected how do you expect to continue processing?  You need to go back to the script and figure out what’s wrong in the function you can’t error handle this situation, unless of course you were expecting it in which case you should have added additional error handling code in the function to deal with it in the first palace.   In this case you redirect the output of the .Append statement so it does not get returned.

When to use Return in a function

So if a function returns every unhandled output why do we need return statement at all?  Keith explains that using a return allows you to return from a function at any time.  there may be several points within a function that you want to stop executing the code in a function and return to the calling script.  This is the equivalent of the Break statement in a switch statement or exit to quite entirely from the script.  It’s not for actually returning the variable and that in his example using Return $proc is equivalent to $proc ; Return.

I’m not disagreeing with Keith here but actually Return $proc may actually be required to return what you want.  What it won’t do is prevent any unhandled output from also being returned.   If we correct his initial script and remove the return statement as follows Then nothing gets returned!

function bar {
 $Proc = Get-Process svchost
 write-host "Returning svchost process objects"
}

We can fix that in two ways put the Return $proc back as the last line of the function or not bother to assign the output of Get-Process to a variable. If you don’t assign the variable $proc then the output of Get-Process is not captured and therefore ends up in the functions returned object. Nice we just turned the problem into the solution.

Advertisements

One thought on “Function Return Values

  1. […] Function Return Values (clan8blog.wordpress.com) […]

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

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