The output and PSDataStreams are available individually from a PowerShell instance. These individual streams, however, do not seem to contain enough information to determine order of an item in one stream compared with an item in another stream.
$ErrorActionPreference = 'Continue'
$powershell = [powershell]::Create().AddScript({
$VerbosePreference = 'Continue'
'output1'
Write-Verbose 'verbose1'
Write-Error 'error1'
Write-Error 'error2'
Write-Verbose 'verbose2'
'output2'
})
$powershell.Invoke()
$powershell.Streams.Verbose
$powershell.Streams.Error
output1
verbose1
$VerbosePreference = 'Continue'
'output1'
Write-Verbose 'verbose1'
Write-Error 'error1'
Write-Error 'error2'
Write-Verbose 'verbose2'
'output2'
: error1
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
$VerbosePreference = 'Continue'
'output1'
Write-Verbose 'verbose1'
Write-Error 'error1'
Write-Error 'error2'
Write-Verbose 'verbose2'
'output2'
: error2
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
verbose2
output2
output1
output2
verbose1
verbose2
$VerbosePreference = 'Continue'
'output1'
Write-Verbose 'verbose1'
Write-Error 'error1'
Write-Error 'error2'
Write-Verbose 'verbose2'
'output2'
: error1
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
$VerbosePreference = 'Continue'
'output1'
Write-Verbose 'verbose1'
Write-Error 'error1'
Write-Error 'error2'
Write-Verbose 'verbose2'
'output2'
: error2
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
> $PSVersionTable
Name Value
---- -----
PSVersion 6.1.0-preview.4
PSEdition Core
GitCommitId 6.1.0-preview.4
OS Microsoft Windows 6.3.9600
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Seems we discussed this before /cc @mklement0
There isn't a way to correlate the streams but you can use the events on the various streams to insert elements into an explicit single output stream in real time. It's a bit clunky but the code to do this would look something like:.
$p = [powershell]::Create().AddScript{
"Output"
$ErrorActionPreference = "continue"
Write-Error "Error"
Write-Verbose -Verbose "Verbose"
"Output2"
$DebugPreference = "continue"
Write-Debug "Debug"
"Output3"
$InformationPreference="continue"
Write-Information "Information"
}
$output = [System.Management.Automation.PSDataCollection[object]]::new()
$p.Streams.Error.add_DataAdded{
$p.Streams.Error.ReadAll().foreach{$output.Add($_)}
}
$p.Streams.Verbose.add_DataAdded{
$p.Streams.Verbose.ReadAll().foreach{$output.Add($_)}
}
$p.Streams.Debug.add_DataAdded{
$p.Streams.Debug.ReadAll().foreach{$output.Add($_)}
}
$p.Streams.Information.add_DataAdded{
$p.Streams.Information.ReadAll().foreach{$output.Add($_)}
}
$p.Invoke($null, $output)
foreach ($item in $output)
{
"output: $item"
}
This will give you a single stream containing all of the records in the order they were written which you can then demultiplex based on type (ErrorRecord, DebugRecord, VerboseRecord, etc.)
@BrucePay That seems pretty good for my purposes. Can I rely on the .DataAdded event handlers to be called in the order that matches the output from the scriptblock?
@alx9r Yes.
I'm trying to do the same thing as above in C# with the .NET Framework using this package (https://www.nuget.org/packages/Microsoft.PowerShell.5.ReferenceAssemblies/). I can't seem to access add_DataAdded from the PowerShell streams (after creating a PowerShell object using PowerShell.Create()).
Do you know how I can use this? I'm not sure if add_DataAdded is only available in what looks like PowerShell or if maybe there's a version difference or something. Thanks.
@DrDinosaur I'm pretty sure I have been using .DataAdded += myEventHandler in C# rather than .add_DataAdded(myEventHandler).
Yeah, I eventually figured that out. I didn't understand PowerShell was trying to make an event handler with that syntax.
Yeah, I eventually figured that out. I didn't understand PowerShell was trying to make an event handler with that syntax.
How?驴
Thanks.
Yeah, I eventually figured that out. I didn't understand PowerShell was trying to make an event handler with that syntax.
How?驴
Thanks.
Yeah, I eventually figured that out. I didn't understand PowerShell was trying to make an event handler with that syntax.
How?驴
Thanks.How to: Subscribe to and Unsubscribe from Events - C# Programming Guide
No way?, only error output events are fired.
Already tried:
`
s_ps.Streams.Verbose.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection
Debug.WriteLine("Progress verbose contains {0} records", records.Count);
};
s_ps.Streams.Progress.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection<ProgressRecord>)sender;
Debug.WriteLine("Progress verbose contains {0} records", records.Count);
};
s_ps.Streams.Verbose.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection<VerboseRecord>)sender;
Debug.WriteLine("Progress verbose contains {0} records", records.Count);
};
s_ps.Streams.Debug.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection<DebugRecord>)sender;
Debug.WriteLine("Progress debug contains {0} records", records.Count);
};
s_ps.Streams.Error.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection<ErrorRecord>)sender;
Debug.WriteLine("Progress error contains {0} records", records.Count);
};
s_ps.Streams.Warning.DataAdding += delegate (object sender, DataAddingEventArgs e) {
var records = (PSDataCollection<WarningRecord>)sender;
Debug.WriteLine("Progress warning contains {0} records", records.Count);
};
Also tried creating runspace events:
pipaLinia = s_ps.Runspace.CreatePipeline();
pipaLinia.Output.DataReady += new EventHandler(Output_DataReady);
pipaLinia.Error.DataReady += new EventHandler(Error_DataReady);
`
I am lost :(