如何流式编程执行ScriptBlock的输出?

时间:2011-03-03 16:13:59

标签: .net powershell streaming

我的程序执行用户指定的脚本块,我希望它以递增方式返回其输出(例如,如果脚本块运行了很长时间)。

然而,ScriptBlock的API似乎没有暴露与管道相关的任何内容!

它有一些看起来像我需要的函数(InvokeWithPipe),但它们是内部的,它们的参数是内部类型。我不想在这里诉诸于反思。

那么,有没有办法访问scriptblock的管道?也许某种强大的解决方法?

1 个答案:

答案 0 :(得分:8)

这里有一些代码可以向ScriptBlock添加一个扩展方法来流输出,为每个输出对象调用一个委托。这是真正的流式传输,因为对象不会在集合中备份。这适用于PowerShell 2.0或更高版本。

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更新,附带参数支持)

希望这有帮助。