0

I want to call Invoke-Expression inside a function and print the output of the command to the console but don't return it from the function since I want to return a specific value from it.

function Foo {
    $command = 'mvn clean package "-Dmaven.test.skip"'
    Invoke-Expression -Command $command | Write-Host

    $result = 'computed return value'
    return $result
}


$fooResult = Foo
Write-Output "fooResult is: ${fooResult}"

This works, but I want to avoid using the evil Write-Host function, so I tried Write-Information instead. But I it seems you can't pipe the output of the Invoke-Expression to Write-Information. When I simply replace Write-Host with Write-Information it behaves like the -MessageData Parameter is not provided (similar when explicitly stating -MessageData).

Is there a way to write the output of Invoke-Expression to the console, but avoid returning it from the function without using Write-Host?

David
  • 1,672
  • 2
  • 13
  • 32
  • "but I want to avoid using the evil `Write-Host` function" - the exact behavior you want (bypass streams, write directly to host) is the very reason `Write-Host` is sometimes described as evil - in other words, you _want to be evil_ here :) – Mathias R. Jessen Apr 15 '21 at 15:09
  • I think there are more disadvantages of using `Write-Host`. As I understand it, I can't redirect the output of it to a file e.g. when I want to redirect all the output of the whole script to a file when invoking it, no? – David Apr 15 '21 at 15:23

2 Answers2

1

You try with OutVariable

function Foo {
    $command = 'mvn clean package "-Dmaven.test.skip"'
    Invoke-Expression -Command $command -OutVariable OutputData | Out-Null

    Write-Information -MessageData "INFO: $OutputData" -INFA "Continue"
    return "something else"
}
metablaster
  • 1,958
  • 12
  • 26
  • 1
    Doing this Powershell tells me that `$OutputData` is `NULL` – David Apr 15 '21 at 15:21
  • I'm sorry, updated my post, please try again. – metablaster Apr 15 '21 at 15:23
  • Now `$OutputData` contains the output but the whole output is still returned from the function as well. Please test your code before posting it. Also the linebreaks seem to not be there anymore. – David Apr 15 '21 at 15:39
  • I edited my post again, and tested code, I'm sorry but I don't know what you mean by "missing line breaks" I don't have `mvn` installed. – metablaster Apr 15 '21 at 15:48
  • This should work, `$outputData` is being directed to the `Information Stream` while `something else` is directed to std out – Santiago Squarzon Apr 15 '21 at 15:55
  • Now only `Write-Output "fooResult is: ${fooResult}"` doesn't print the Linebreaks. Except that it works now, thanks :) – David Apr 16 '21 at 06:03
0

Output to the screen is the Powershell default unless you tell it to do otherwise. So, Write-* is almost moot, in many cases. Yet, folks have their reasons for using Write-* cmdlets.

There are several ways to write to the screen and even save to a variable and write to the screen at the same time.

  • variable squeezing
  • Out-String
  • Out-Host
  • Tee-Object

The aforementioned and more have been regularly covered.

Example web hits:

https://ridicurious.com/2017/06/30/3-ways-to-store-display-results-infrom-a-powershell-variable-at-the-same-time

https://mikefrobbins.com/2014/03/28/powershell-output-the-result-of-a-command-and-assign-it-to-a-variable-in-one-line

Get-Process a* -OutVariable process
($process = Get-Process a*)
Get-Process a* | Tee-Object -Variable p

Your post can even be seen as a duplicate of this similar use case:

Invoke-expression output on Screen and in a variable

Invoke-Expression $var -OutVariable | Tee-Object -Variable out 

Invoke-Expression $var | Tee-Object C:\Path\To\File.txt

Running executables from Powershell is also a well-documented use case. See this from MS.

• PowerShell: Running Executables

https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx

postanote
  • 15,138
  • 2
  • 14
  • 25
  • The `Tee-Object` writes the output to the pipeline, which leads to the function including it in the return value, which I want to avoid. – David Apr 29 '21 at 10:29