Function return value in PowerShell

Solution 1:

PowerShell has really wacky return semantics - at least when viewed from a more traditional programming perspective. There are two main ideas to wrap your head around:

  • All output is captured, and returned
  • The return keyword really just indicates a logical exit point

Thus, the following two script blocks will do effectively the exact same thing:

$a = "Hello, World"
return $a

 

$a = "Hello, World"
$a
return

The $a variable in the second example is left as output on the pipeline and, as mentioned, all output is returned. In fact, in the second example you could omit the return entirely and you would get the same behavior (the return would be implied as the function naturally completes and exits).

Without more of your function definition I can't say why you are getting a PSMethod object. My guess is that you probably have something a few lines up that is not being captured and is being placed on the output pipeline.

It is also worth noting that you probably don't need those semicolons - unless you are nesting multiple expressions on a single line.

You can read more about the return semantics on the about_Return page on TechNet, or by invoking the help return command from PowerShell itself.

Solution 2:

This part of PowerShell is probably the most stupid aspect. Any extraneous output generated during a function will pollute the result. Sometimes there isn't any output, and then under some conditions there is some other unplanned output, in addition to your planned return value.

So, I remove the assignment from the original function call, so the output ends up on the screen, and then step through until something I didn't plan for pops out in the debugger window (using the PowerShell ISE).

Even things like reserving variables in outer scopes cause output, like [boolean]$isEnabled which will annoyingly spit a False out unless you make it [boolean]$isEnabled = $false.

Another good one is $someCollection.Add("thing") which spits out the new collection count.

Solution 3:

With PowerShell 5 we now have the ability to create classes. Change your function into a class, and return will only return the object immediately preceding it. Here is a real simple example.

class test_class {
    [int]return_what() {
        Write-Output "Hello, World!"
        return 808979
    }
}
$tc = New-Object -TypeName test_class
$tc.return_what()

If this was a function the expected output would be

Hello World
808979

but as a class the only thing returned is the integer 808979. A class is sort of like a guarantee that it will only return the type declared or void.

Solution 4:

As a workaround I've been returning the last object in the array that you get back from the function... It is not a great solution, but it's better than nothing:

someFunction {
   $a = "hello"
   "Function is running"
   return $a
}

$b = someFunction
$b = $b[($b.count - 1)]  # Or
$b = $b[-1]              # Simpler

All in all, a more one-lineish way of writing the same thing could be:

$b = (someFunction $someParameter $andAnotherOne)[-1]