如何流以编程执行脚本块的输出? [英] How to stream the output of a programmatically executed ScriptBlock?
问题描述
我的程序执行用户指定的scriptblocks,我希望它逐步恢复其输出(例如,在情况下,脚本块运行了很长一段时间)。
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).
不过,脚本块的API似乎并没有暴露任何管道相关的!
However, the API of ScriptBlock does not seem to expose anything pipeline-related!
它有一些功能,看上去就像他们在做什么,我需要(InvokeWithPipe),但他们内部和他们的论据是内部类型。我讨厌诉诸黑客进入反射这里。
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?
推荐答案
下面是一些code,将增加一个扩展方法,以脚本块流输出,调用一个委托为每个输出对象。这是因为这些对象不会备份集合中的真正的流媒体。这是PowerShell的2.0或更高版本。
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
}
}
例如:
// 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}});
(更新2011年3月7日与参数的支持)
(updated 2011/3/7 with parameter support)
希望这有助于。
这篇关于如何流以编程执行脚本块的输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!