Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I capture .NET trace output from a Powershell job?

I am using a .NET component in Powershell which uses Trace.TraceWarning, Trace.TraceInformation etc.

I want to output these traces to the console when I run my Powershell script.

This works when I use the component in the current session. For example (simulating the effect of trace) gives me 'Hello' output to the console:

 $listener = new-object "system.diagnostics.consoletracelistener"
 [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
 [System.Diagnostics.Trace]::TraceInformation("Hello")

But if I do the same within a Powershell job I get no output, even though ConsoleTraceListener should be writing to STDOUT which in turn I expected to get captured by the job. (Interestingly Console.WriteLine doesn't work from a job either - but Write-Host does).

I am starting my job like so:

$work = {
     $listener = new-object "system.diagnostics.consoletracelistener"
     [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
     [System.Diagnostics.Trace]::TraceInformation("Hello")
}
$job = Start-Job -RunAs32 -ScriptBlock $work
$job | Receive-Job -Wait
like image 500
Jack Ukleja Avatar asked Jan 27 '15 14:01

Jack Ukleja


Video Answer


1 Answers

I remember running into something similar to this years ago where expected STDOUT and STDIN weren't behaving as expected with start-job and exe's. I ended up using System.Diagnostics.Process and redirecting the STDIN and STDOUT. Here's an example that demonstrates this workaround in a way that may assist you with what you are trying to do.

#added extra trace messages with Get-Date and implemented a random delay for demo purpose
$work = {
     $listener = new-object "system.diagnostics.consoletracelistener"
     [System.Diagnostics.Trace]::Listeners.Add($listener) | Out-Null
     1..10 | % {
         Start-Sleep $(Get-Random 5)
         [System.Diagnostics.Trace]::TraceInformation((Get-Date))
    }
}
#Create a process
$process = New-Object System.Diagnostics.Process 
$process.StartInfo.UseShellExecute = $false
#redirect stdout
$process.StartInfo.RedirectStandardOutput = $true
#call powershell
$process.StartInfo.FileName = "powershell.exe"
#pass the $work scriptblock
$process.StartInfo.Arguments = "-noprofile -command $work"
#start the process
$process.Start() | Out-Null
#readlines as they come in and exit when process is done
while(-not $process.HasExited){
    $process.StandardOutput.ReadLine()
}

Output:

powershell.exe Information: 0 : 01/30/2015 12:27:17
powershell.exe Information: 0 : 01/30/2015 12:27:20
powershell.exe Information: 0 : 01/30/2015 12:27:21
powershell.exe Information: 0 : 01/30/2015 12:27:25
powershell.exe Information: 0 : 01/30/2015 12:27:26
powershell.exe Information: 0 : 01/30/2015 12:27:28
powershell.exe Information: 0 : 01/30/2015 12:27:29
powershell.exe Information: 0 : 01/30/2015 12:27:33
powershell.exe Information: 0 : 01/30/2015 12:27:36
powershell.exe Information: 0 : 01/30/2015 12:27:40
like image 90
StephenP Avatar answered Oct 03 '22 23:10

StephenP