0

If I start a job, and that job outputs messages to the Information stream (or any stream for that matter), how can I capture that into a variable, or simply output it after I receive the job?

$script = {
    [PSCustomObject]@{ "CoolProperty" = "CoolValue" }
    Write-Information "Returning a cool object" -InformationAction "Continue"
}

Start-Job -Name "test" -ScriptBlock $script | Out-Null
Wait-Job -Name "test" | Out-Null
$result = Receive-Job -Name "test" 6>&1
Remove-Job -Name "test"

The above code will output

Returning a cool object

to the console, but I would like to capture that and output it to the log file I'm using for the overall script, e.g.:

$JustTheInfoStreamFromJob | Out-File "c:\file.log" -Append

I don't want to log the captured $result, because it also contains the Output stream (i.e. the object). I only want to log the Information stream. So I'm looking for a way to separate that out.

I see that there is an -InformationVariable parameter, but I don't understand how to use it, or if it's relevant for my question. I've tried a few methods of redirection, but I have very little idea what I'm doing when it comes to streams.

This question gives me some hints, but not enough to understand.

This question is very similar but appears to have been asked before the Information stream existed. I'd rather not use Transcripts unless it's necessary; I feel like there should be a better way.

Some answers reference the ChildJobs, Output, and Information properties of a Job object, but I'm having a hard time understanding how to use them, as they are always null in my simple tests.

Thanks for your time.

Solved

Thanks to @Santiago Squarzon and @Steven for two different working solutions:

Remove-Job "test"
$script = {
    [PSCustomObject]@{ "CoolProperty" = "CoolValue" }
    Write-Information "Returning a cool object"
}

Start-Job -Name "test" -ScriptBlock $script | Out-Null
$job = Get-Job -Name "test" -IncludeChildJob # Steven's solution
$job | Wait-Job | Out-Null
$info = $job.Information # Steven's solution
$result = Receive-Job -Name "test" -InformationVariable info2 # Santiago Squarzon's solution
Remove-Job -Name "test"

$result
"---"
$info
"---"
$info2

This allows me to capture the job's output and the job's Info stream separately (two different ways):

CoolProperty RunspaceId
------------ ----------
CoolValue    f49c78bd-eda3-4c47-a6bc-d89a146618e9
---
Returning a cool object
---
Returning a cool object
mmseng
  • 735
  • 9
  • 24
  • 1
    Not entirely sure why would you do such a thing but for the sake of answering your question you need to redirect the information stream to stdout. Like this: `$job = Receive-Job -Name "test" 6>&1` – Santiago Squarzon Apr 03 '21 at 01:09
  • That is one of the solutions I tried (actually `*>&1`), however the issue is that this sends both the Output stream and the Info stream to the variable. I only want to log the Info stream, so I'm looking for a way to separate out the Info stream and log just that. Admittedly I did not make that clear in my code. – mmseng Apr 03 '21 at 01:19
  • 1
    What do you mean by Output stream, what cmdlet there do you think is directing to Ouput stream? – Santiago Squarzon Apr 03 '21 at 01:24
  • I tried to update the question to make it more clear. Capturing the output of `Receive-Job "test" 6>&1` into a variable captures everything output by the job in both the job's Output stream (i.e. stream #1) plus the job's Information stream (#6). I'm trying to capture the job's Information stream separately. I apologize if my nomenclature is not accurate, I hope that makes sense. – mmseng Apr 03 '21 at 01:37
  • 2
    You got it right with `-InformationVariable`, try `$result = Receive-Job -Name "test" -InformationVariable infoStream`. You'll see you'r PSCustomObject stored in the `$result` variable and the log in the `$infoStream` variable :) – Santiago Squarzon Apr 03 '21 at 01:46
  • Thank you. That worked. When I tried `-InformationVariable` before I made the classic mistake of specifying a variable (i.e. `$infoStream`), instead of a variable _name_ (i.e. `infoSteam`). Steven's answer also worked, once I got my order of operations correct. – mmseng Apr 03 '21 at 01:54
  • Updated question with example solution(s). – mmseng Apr 03 '21 at 02:03

1 Answers1

1

The different Streams are stored separately in the job object:

State         : Completed
HasMoreData   : True
StatusMessage :
Location      : localhost
Command       :  Write-Information "something"
JobStateInfo  : Completed
Finished      : System.Threading.ManualResetEvent
InstanceId    : ff5d1155-aca1-40fa-8e4e-dce6b87c709c
Id            : 2
Name          : test
ChildJobs     : {Job3}
PSBeginTime   : 4/2/2021 9:41:26 PM
PSEndTime     : 4/2/2021 9:41:26 PM
PSJobTypeName : BackgroundJob
Output        : {}
Error         : {}
Progress      : {}
Verbose       : {}
Debug         : {}
Warning       : {}
Information   : {}

Notice the child Job, but you can get at the information stream with something like:

(Get-Job -Name test -IncludeChildJob).Information

In the above example it will return "something", reference the command from the job.

Reference here there's some other good information as well.

Steven
  • 6,817
  • 1
  • 14
  • 14
  • Thanks. This worked once I got my order of operations right. I needed to be capturing that before receiving the job, since `Receive-Job` removes that data. Or I suppose the `-Keep` parameter would have worked too. – mmseng Apr 03 '21 at 01:55