Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell Receive-Job Output To Variable Or File But Not Screen

Tags:

powershell

I am trying to get the job details without outputting the data to the screen. However, regardless of what option I try, the job logs always get sent to the console. Any ideas on how to save the logs in a variable or file without outputting that data to console?

Receive-Job -Id $id -Keep -ErrorAction Continue > C:\Temp\Transcript-$VM.txt

$info = Receive-Job -Id $id -Keep -ErrorAction Continue
like image 919
Pie Avatar asked Oct 15 '22 09:10

Pie


1 Answers

You state that your job uses Write-Host output and that you're running Windows PowerShell v5.1.

In order to also capture Write-Host output - which in v5+ is sent to the information stream (stream number 6) - use redirection 6>&1:

# Capture both success output and information-stream output
# (Write-Host) output in $info.
$info = Receive-Job -Id $id -Keep -ErrorAction Continue 6>&1

Unfortunately, due to a known bug, you'll still get console output as well (bug is still present in PowerShell Core 7.0.0-preview.5).

Catch-all redirection *>&1 normally routes all streams through the success output stream.

Unfortunately, due to the bug linked to above, the following streams cannot be captured or redirected at all when using background jobs or remoting:

  • verbose messages (4)
  • debug messages (5)

The only workaround is to capture the streams inside the job and save them to a file from there, and then access the files from the caller later.
Of course, this requires that you have control over how the jobs are created.

A simplified example:

# Redirect all output streams *inside* the job to a file...
Start-Job { 
 & { 
   # The job's commands go here.
   # Note that for any *verbose* output to be captured,
   # verbose output must explicitly turned on, such as with
   # the -Verbose common parameter here.
   # You can also set $VerbosePreference = 'Continue', which 
   # cmdlets (including advanced functions/scripts) will honor.
   'success'; write-verbose -Verbose 'verbose'; write-host 'host' 
 } *> $HOME/out.txt 
} | Receive-Job -Wait -AutoRemove
# ... then read the resulting file.
Get-Content $HOME/out.txt

Note that I've used a full path as the redirection target, because, unfortunately, in v6- versions of PowerShell script blocks executed in background jobs do not inherit the caller's current location. This will change in PowerShell Core v7.0.

like image 95
mklement0 Avatar answered Oct 23 '22 19:10

mklement0