Write-Output fails from within scriptblock

by cswan at 2013-04-11 13:42:30

I am running multiple copies of a script in parallel and would like to be able to write output to the console from within the script while the script is processing. If I use Invoke-command, it works because it is in the same run space, but fails with Start-Job. Is there an easy way to do it with Start-Job?
Thanks for your help.

$ScriptBlock = {Write-Output "Message from within scriptblock"}
Invoke-command -scriptblock $ScriptBlock
by mjolinor at 2013-04-11 16:06:58
Typeically you use Recieve-Job to get the output from a job. If you want it from multiple jobs while they’re running you’ll need to cycle through them.
Unfortunately this isn’t going to give you just the ouput stream, but all of the streams (Output,Error,Warning,Verbose, and Debug), and you don’t have much control over how it’s displayed, so it can be difficult to tell which output is coming from which job.

There is at least one other way to get the output from a background job - reading it directly from the output buffers of the child jobs.

Here’s a demo script that shows how to do that.

$sb = {
$VerbosePreference = 'Continue'
for ($i = 1; $i -le 100; $i++ )
{
start-sleep -Milliseconds 150
Write-Verbose "$(get-date)"
write-progress -activity "Search in Progress" -status "$i% Complete:" -percentcomplete $i;}
}

$job = start-job -ScriptBlock $sb
$verbose = ($job.ChildJobs[0].Verbose)

While ($job.State -ne 'Completed')
{
$job.ChildJobs |
foreach {
Start-Sleep -seconds 1
$Pct_Complete = $_.Progress | select -last 1 | select -ExpandProperty PercentComplete
Write-Host "rBackground job $&#40;$_.ID&#41; is $Pct_Complete percent completed.&quot; -ForegroundColor Cyan <br> While &#40;$verbose.count&#41;{<br> Write-Host $verbose[0] -ForegroundColor Gray<br> $verbose.removeat&#40;0&#41;}<br> }<br> <br>}<br>write-host &quot;nDone!"


Note that you’re reading the output selectively by buffer, and handling it as plain text, so you can use Write-Host (checking to see of Don online before I type that) and have some control over how it’s displayed. With multiple jobs producing collated output on the screen, you might want to cycle through a color pallete, giving the output from each job it’s own foreground or background color, add a job-identification prefix to each one, indent the output differently for each job, or some combination of those so it’s easy to visually distinguish the output of one job from another.

Note that In ithe example I’m reading from the Verbose stream, and removing the output as it’s written so it doesn’t get re-written on each pass. This does seem to affect the Verbose output in the Receive-Job buffer. If you do a Receive-Job on it after it’s finished, you’ll still get all the Verbose output again.