Хостинг PowerShell: PowerShell против Runspace против RunspacePool против трубопровода

Я пытаюсь добавить довольно ограниченную поддержку PowerShell в свое приложение: я хочу иметь возможность периодически запускать определенный пользователем сценарий PowerShell и показывать любой вывод и (в конечном итоге) иметь возможность обрабатывать уведомления о ходе выполнения и запросы пользователей. Мне не нужна интерактивная поддержка в стиле командной строки или (я думаю) удаленный доступ или возможность запуска нескольких одновременных сценариев, если только пользовательский сценарий не делает это сам из оболочки, которую я размещаю. В конце концов я захочу запустить скрипт асинхронно или в фоновом потоке и, возможно, заполнить оболочку некоторыми начальными переменными и, возможно, командлетом, но настолько "причудливым", как эта функция, скорее всего, получится.

Я читал документацию MSDN о написании кода хост-приложения, но, несмотря на то, что он радостно объясняет, как создать объект PowerShell, или Runspace, или RunspacePool, или Pipeline, там нет указаний на то, почему один из этих подходов предпочтительнее другого.

Я думаю, что я отношусь к одному из этих двух, но мне нравятся некоторые отзывы о том, какой подход лучше выбрать:

PowerShell shell = PowerShell.Create();
shell.AddCommand(/* set initial state here? */);
shell.AddStatement();
shell.AddScript(myScript);
shell.Invoke(/* can set host! */);

или:

Runspace runspace = RunspaceFactory.CreateRunspace(/* can set host and initial state! */);
PowerShell shell = PowerShell.Create();
shell.Runspace = runspace;
shell.AddScript(myScript);
shell.Invoke(/* can set host here, too! */);

(Одним из обязательных методов класса PSHost -derived является EnterNestedPrompt(), и я не знаю, может ли пользовательский скрипт, который я запускаю, вызывать его, или нет. Если это возможно, то я Вы будете ответственны за "запуск нового вложенного цикла ввода" (как здесь)... если это повлияет на то, какой путь выбрать выше, это также было бы полезно знать.)

Спасибо!

Ответ 1

Кто они такие?

  • Трубопровод

Конвейер - это способ объединения команд внутри сценария powershell. Пример: вы " Get-ChildeItem " вывод из Get-ChildeItem в Where-Object с помощью | отфильтровать их:

Get-ChildItem | Where-Object {$_}
  • PowerShell Object

Объект PowerShell ссылается на сеанс PowerShell, аналогичный тому, который вы получаете при запуске powershell.exe.

  • пространство выполнения

Каждый сеанс powershell имеет свое собственное пространство выполнения (вы всегда будете получать выходные данные из Get-Runspace). Он определяет состояние сеанса powershell. Следовательно, InitialSessionState объект/свойство пространства выполнения. Вы можете решить создать новый сеанс PowerShell с собственным пространством выполнения из PowerShell, чтобы включить многопоточность.

  • RunspacePool

И последнее, но не менее важное - RunspacePool. Как следует из названия, это пул пространств выполнения (или сеансов PowerShell), которые можно использовать для обработки множества завершенных задач. Как только одно из пространств выполнения в пуле завершило свою задачу, она может выполнить следующую задачу, пока все не будет сделано. (100 вещей, которые нужно сделать с 10 пространствами выполнения: в avarage они обрабатывают по 10 в каждом, но один может обрабатывать 8, в то время как два других обрабатывают 11...)


Когда использовать что?

  • Трубопровод

Конвейер используется insed из скриптов. Это облегчает создание сложных сценариев и должно использоваться как можно чаще.

  • PowerShell Object

Объект powershell используется всякий раз, когда вам нужен новый сеанс powershell. Вы можете создать его внутри существующего скрипта, будь то С# или Powershell. Это полезно для легкого многопоточности. Сам по себе он создаст сеанс по умолчанию.

  • пространство выполнения

Если вы хотите создать нестандартный сеанс powershell, вы можете манипулировать объектом runspace перед созданием сеанса powershell с ним. Это полезно, когда вы хотите совместно использовать синхронизированные переменные, функции или классы в дополнительных пространствах выполнения. Чуть более сложная многопоточность.

  • RunspacePool

Как упоминалось ранее, это тяжелый инструмент для тяжелой работы. Когда одно выполнение скрипта занимает часы, и вам нужно делать это очень часто. Например, в сочетании с удаленным взаимодействием вы можете одновременно установить что-то на каждом узле большого кластера и т.п.

Ответ 2

Вы переосмысливаете это. Код, который вы показываете в примерах, является хорошим началом. Теперь вам просто нужно прочитать результат Invoke() и проверить потоки ошибок и предупреждений.

Хост PowerShell предоставляет несколько хуков, которые RunSpace может использовать для связи с пользователем, таких как вывод потока и форматирования, показ прогресса, сообщения об ошибках и т.д. Для того, что вы хотите сделать, вам не нужен хост PowerShell. Вы можете прочитать результаты обратно из выполнения скрипта с помощью класса PowerShell, проверить наличие ошибок, предупреждений, прочитать выходные потоки и показать уведомление пользователю, используя возможности вашего приложения. Это будет гораздо проще и эффективнее, чем написать весь хост PowerShell, чтобы отобразить окно сообщения при обнаружении ошибок.

Кроме того, у объекта PowerShell есть Runspace при его создании, вам не нужно указывать его. Если вам нужно сохранить пространство выполнения для сохранения среды, просто сохраните весь объект PowerShell и очищайте Commands и все Stream каждый раз после вызова Invoke.

Следующий вопрос, который вы должны задать, - как обработать результат PowerShell::Invoke() и прочитать PowerShell::Streams.