My program executes user-specified scriptblocks and I want it to return its output incrementally (e.g. in case the scriptblock runs for a long time).
However, the API of ScriptBlock does not seem to expose anything pipeline-related!
It has some functions that look like they're what I need (InvokeWithPipe), but they're internal and their arguments are of internal types. I'd hate to resort to hacking into reflection here.
So, is there a way to access the scriptblock's pipeline? Maybe some kind of robust workaround?
Here's some code that will add an extension method to ScriptBlock to stream output, calling a delegate for each output object. It is true streaming as the objects are not backed up in a collection. This is for PowerShell 2.0 or later.
public static class ScriptBlockStreamingExtensions {
public static void ForEachObject<T>(
this ScriptBlock script,
Action<T> action,
IDictionary parameters) {
using (var ps = PowerShell.Create()) {
ps.AddScript(script.ToString());
if (parameters != null) {
ps.AddParameters(parameters);
}
ps.Invoke(Enumerable.Empty<object>(), // input
new ForwardingNullList<T>(action)); // output
}
}
private class ForwardingNullList<T> : IList<T> {
private readonly Action<T> _elementAction;
internal ForwardingNullList(Action<T> elementAction) {
_elementAction = elementAction;
}
#region Implementation of IEnumerable
// members throw NotImplementedException
#endregion
#region Implementation of ICollection<T>
// other members throw NotImplementedException
public int Count {
get {
return 0;
}
}
#endregion
#region Implementation of IList<T>
// other members throw NotImplementedException
public void Insert(int index, T item) {
_elementAction(item);
}
#endregion
}
}
Example:
// execute a scriptblock with parameters
ScriptBlock script = ScriptBlock.Create("param($x, $y); $x+$y");
script.ForEachObject<int>(Console.WriteLine,
new Dictionary<string,object> {{"x", 2},{"y", 3}});
(updated 2011/3/7 with parameter support)
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With