Как транслировать вывод программно исполняемого ScriptBlock - PullRequest
6 голосов
/ 03 марта 2011

Моя программа выполняет указанные пользователем скрипт-блоки, и я хочу, чтобы она возвращала свой вывод постепенно (например, в случае, если скрипт-блок работает долго).

Однако, API ScriptBlock, похоже, ничего не раскрываетотносящиеся к конвейеру!

У него есть некоторые функции, которые выглядят так, как будто они мне нужны (InvokeWithPipe), но они внутренние и их аргументы имеют внутренние типы.Я бы не хотел прибегать к взлому в рефлексии.

Итак, есть ли способ получить доступ к конвейеру скриптового блока?Может быть, какой-то надежный обходной путь?

1 Ответ

8 голосов
/ 07 марта 2011

Вот некоторый код, который добавит метод расширения в 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 с поддержкой параметров)

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...