powershellrunspace

Powershell stream events


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?


Solution

  • 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: