Best way to return values from a function that writes to STDOUT

another approach:

  1. in your function, do logging via Write-Information.
  2. in the calling scope, call the function inside a sub-expression and redirect the information stream of the sub-expression to stdout. Be sure to assign the return value of the function to a variable, or it will also go to stdout.

eg

function bar() {
  Write-Information "Hello from bar()"
  return 4
}

$($x = bar) 6>&1

Write-Output "in main `$x = $x"

If you're on an old version of powershell and can't use Write-Information the same approach works with Write-Verbose. In that case you'd redirect as 4>&1. With verbose you'll get the ugly yellow/black and "VERBOSE" text, unless you're redirecting the stdout of the overall script into a file, in which case the VERBOSE: tag will be omitted.


In PowerShell all non-captured output inside a function is returned, not just the argument of return. From the documentation:

In PowerShell, the results of each statement are returned as output, even without a statement that contains the return keyword.

It doesn't matter if the function looks like this:

function Foo {
  'foo'
}

or like this:

function Foo {
  'foo'
  return
}

or like this:

function Foo {
  return 'foo'
}

it will return the string foo either way.

To prevent output from being returned, you can

  • write to the host or one of the other ouptput streams (depending on the type of output you want to create):

    Function a {
      Write-Host 'some text'
      Write-Verbose 'verbose message'
      Write-Information 'info message'   # requires PowerShell v5 or newer
      $a = 4
      return $a
    }
    

    Side note: Write-Information is not available prior to PowerShell v5 when the information stream was introduced, and starting with that version Write-Host also writes to that stream rather than directly to the host console.

  • capture the output in a variable or "assign" it to $null:

    Function a {
      $var = Write-Output 'some text'
      $null = Write-Output 'some text'
      $a = 4
      return $a
    }
    
  • or redirect the output to $null:

    Function a {
      Write-Output 'some text' | Out-Null
      Write-Output 'some text' >$null
      $a = 4
      return $a
    }