Home > Software engineering >  Powershell stream events
Powershell stream events

Time:12-09

I wonder if it's possible to subscribe to the current Powershell session event stream so that every time some information/warning/error etc is added to the stream I can read it as an object. I was able to subscribe to DataAdded events of the 3 streams mentioned above, but for some reason I can intercept events only from error stream

$InformationPreference = 'Continue'

$ps = [PowerShell]::Create("CurrentRunspace")
$ps.Streams.Information.Add_DataAdded({
     # THE EVENT IS NEVER TRIGGERED
    $ps.Streams.Information.ReadAll().ForEach{ 
        Write-Host ($_ | Out-String)
    }
})
$ps.Streams.Warning.Add_DataAdded({
    # THE EVENT IS NEVER TRIGGERED
    $ps.Streams.Warning.ReadAll().ForEach{ 
        Write-Host ($_ | Out-String)
    }
})
$ps.Streams.Error.Add_DataAdded({
    #WORKS FINE
    $ps.Streams.Error.ReadAll().ForEach{ 
        Write-Host ($_ | Out-String)
    }
})

$ps.AddScript({
    Write-Information 'Some Information'
    Write-Warning 'Some Warning'
    Write-Error 'Some Error'
}).Invoke()

Any ideas why Warning and Information streams don't trigger events?

CodePudding user response:

Here is an example to redirect all streams of a script block to the success stream, keeping the original formatting intact and still be able to differentiate the kind of stream.

& {
    [PSCustomObject]@{ Foo = 42; Bar = 23 } | Format-Table  # Output
    $DebugPreference = 'Continue'
    Write-Debug 'Some Debug'
    Write-Information 'Some Information'
    Write-Warning 'Some Warning'
    Write-Error 'Some Error'

} *>&1 | ForEach-Object -PV record { $_ } | Out-String -Stream | ForEach-Object {
    # Process a single line of formatted output

    $prefix = switch( $record ) {
        { $_ -is [Management.Automation.DebugRecord] }       { 'DBG'; break }
        { $_ -is [Management.Automation.InformationRecord] } { 'INF'; break }
        { $_ -is [Management.Automation.WarningRecord] }     { 'WRN'; break }
        { $_ -is [Management.Automation.ErrorRecord] }       { 'ERR'; break }
        default                                              { 'OUT' }
    }

    # Prepend prefix and output current line 
    "[$prefix] $_"  
}

Output:

[OUT]        
[OUT] Foo Bar
[OUT] --- ---
[OUT]  42  23
[OUT]        
[OUT]
[DBG] Some Debug
[INF] Some Information
[WRN] Some Warning    
[ERR] 
[ERR]   [PSCustomObject]@{ Foo = 42; Bar = 23 } | Format-Table  # Output
[ERR]   Write-Debug 'Some Debug'
[ERR]     Write-Information 'Some Information'
[ERR]     Write-Warning 'Some Warning'
[ERR]     Write-Error 'Some Error'
[ERR]
[ERR]  : Some Error
[ERR] In ***\RedirectAllStreams.ps1:1 Char:1
[ERR]   & {
[ERR]   ~~~
[ERR]       CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
[ERR]       FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
[ERR]

Remarks:

  • *>&1 enter image description here

  • Related