1

I'm new to powershell and it looks like I have trouble with it's concept of pipes. As I understand:

  • Write-Host writes "on the console" but can not be reused/ captured from other scripts
  • Write-Output puts something into the pipe. If the content of the pipe isn't used elsewhere, it's dumped onto the console. A calling script can use the output.

In virtually all scripting languages I know you can write to the console from anywhere in a way it can be used from calling scripts and without affecting the return value of a function.

So:

  • Whats the benefit of this? At the moment, it looks elegant by design but not really practical.
  • How can I write to the script output from within a function without affecting it's return value (no, I can't use [Write-Host][1])
  • How can I write to the script output from within a callback/ event like in

    $ect = Register-ObjectEvent -InputObject $ps -Action { Write-Somewhere $EventArgs.Data } -EventName 'ErrorDataReceived' 
    

Background: the script is called from a wrapper file, called from a wrapper file called from Jenkins. Write-Output is correctly logged but I can not use it everywhere. I want to avoid dumping text into a temp file and read it back at the end to conserve timing.

1

A helpful effect of the distinction between Write-Host and Write-Output is that you can insert logging (Write-Host) in your functions without messing up the values they actually return to their callers (Write-Output).

Speaking of returning to callers, simply letting a value come out of an expression or cmdlet invocation will pass it on as output. Therefore, 5 on a line by itself and Write-Output 5 are equivalent. A somewhat tricky concept is that PowerShell scripts don't have return values in the same sense as most programming languages do. Returning a value with the Return keyword is indistinguishable from allowing the value out the output pipeline and then exiting the function. In other words, 5; break is the same as Return 5. The script output (which may be multiple objects) is the return value.

Objects that come out of script blocks registered as event actions are automatically stashed in the Output property of the event's job object, which is what you get back from Register-ObjectEvent if you use -Action to provide a script block. Here is an example script that notes the current date and time every time a timer fires:

$timer = New-Object System.Timers.Timer
$timer.Interval = 2000
$myEvent = Register-ObjectEvent $timer -EventName 'Elapsed' -Action {Get-Date}
$timer.Start()

The $myEvent variable will receive the job object from Register-ObjectEvent. $myEvent.Output will be an ever-growing array of times, one from every run of Get-Date in the event handler. (There are some automatically defined variables that may be useful in such handlers.) In your case, once whatever's done generating the callbacks finishes, you could output $ect.Output to pass the captured data on to the calling script.

Alternatively, if you don't want to deal with custom event handlers, you can leave off the script block and instead supply a source identifier that names the event subscription. We could replace the $myEvent line from the previous example with this:

Register-ObjectEvent $timer -EventName 'Elapsed' -SourceIdentifier 'MyEvent'

Now events go into the event queue, tagged with our source identifier. To retrieve them later, we use Get-Event:

Get-Event -SourceIdentifier 'MyEvent'
  • Makes sense to me but I can try this earliest next wendesday. I'll either post my own answer or accept your one. Nevertheless: +1, thank you – Peter Schneider Oct 27 '17 at 21:27
0

At first, if you want details how Write-Output works (and is intended to work), see BenN's answer.

Neither Write-Output nor Write-Host is really working for me. But Powershell has more options for writing on screen and to output channels to offer. I opted to use Write-Verbose. I am not in control of the calling script but luckily, the Verbose-channel is already merged to standard output.

If that's not the case, you need to merge debug-output into standard-output manually:

.\test_writing_to_debug_output.ps1 4>&1 > a_logfile.txt

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.