I'm executing a script with the PowerShell SDK, which makes use of all different streams (information, warning, verbose, ..). I can capture the output from them correctly, but not in the sequence they are generated. As an example, here is a console app (C#, .NET 7, installed the NuGet package Microsoft.PowerShell.SDK):
using System.Management.Automation.Runspaces;
var runSpace = RunspaceFactory.CreateRunspace(InitialSessionState.CreateDefault());
runSpace.Open();
var instance = System.Management.Automation.PowerShell.Create(runSpace);
instance.AddScript("""
$VerbosePreference = 'Continue'
Write-Verbose "Line 1"
Write-Output "Line 2"
Write-Verbose "Line 3"
Write-Information "Line 4"
Write-Information "Line 5"
Write-Verbose "Line 6"
"""
);
var output = instance.Invoke();
foreach (var o in output)
{
Console.WriteLine($"[N]: {o}");
}
foreach (var v in instance.Streams.Verbose)
{
Console.WriteLine($"[V]: {v}");
}
foreach (var i in instance.Streams.Information)
{
Console.WriteLine($"[I]: {i}");
}
As you can see I'm returning different results on different streams. When I output them like that of course, they are no longer in the correct order:
[N]: Line 2
[V]: Line 1
[V]: Line 3
[V]: Line 6
[I]: Line 4
[I]: Line 5
I have been looking at the objects provided by instance.Streams.Information
, instance.Streams.Verbose
, etc. - but I could not find a property that would let me sort them. Interestingly instance.Streams.Information
has a TimeGenerated
, but it is missing from all the other stream objects!
So I'm stumped how I could accomplish this, would it be possible to get these sorted based on the time they were generated?
You'll want to subscribe to the relevant event on each stream collection up front, rather then waiting until execution has finished.
To do so, register handlers for the
DataAdded
event on each relevantinstance.Streams.*
property:Now we just need to define and implement the
ConsumeStreamOutput
method that will handle the events. It needs to expect different types of output based on stream it's written to.The above should give you an output like:
Of course you can change this method to just collect the data to a single queue or similar if you need to process the data elsewhere.