如何流以编程执行脚本块的输出? [英] How to stream the output of a programmatically executed ScriptBlock?

查看:133
本文介绍了如何流以编程执行脚本块的输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序执行用户指定的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆