Хостинг PowerShell: PowerShell против Runspace против RunspacePool против Pipeline
Я пытаюсь добавить довольно ограниченную поддержку 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
методы класса EnterNestedPrompt()
и я не знаю, может ли пользовательский скрипт, который я запускаю, вызвать его или нет. Если это возможно, то я буду отвечать за "запуск нового вложенного цикла ввода" ( как здесь)... если это повлияет на то, какой путь выбрать выше, это также было бы полезно знать.)
Спасибо!
1 ответ
Кто они такие?
- Трубопровод
Конвейер - это способ объединения команд внутри сценария powershell. Пример: вы "труба" выход из 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. Вы можете создать его внутри существующего скрипта, будь то C# или Powershell. Это полезно для легкой многопоточности. Сам по себе он создаст сеанс по умолчанию.
- пространство выполнения
Если вы хотите создать нестандартный сеанс powershell, вы можете манипулировать объектом runspace перед созданием сеанса powershell с ним. Это полезно, когда вы хотите совместно использовать синхронизированные переменные, функции или классы в дополнительных пространствах выполнения. Чуть более сложная многопоточность.
- RunspacePool
Как упоминалось ранее, это тяжелый инструмент для тяжелой работы. Когда одно выполнение скрипта занимает часы, и вам нужно делать это очень часто. Например, в сочетании с удаленным взаимодействием вы можете одновременно установить что-то на каждом узле большого кластера и т.п.
Вы переосмысливаете это. Код, который вы показываете в примерах, является хорошим началом. Теперь вам просто нужно прочитать результат Invoke() и проверить потоки ошибок и предупреждений.
Хост PowerShell предоставляет несколько хуков, которые RunSpace может использовать для связи с пользователем, таких как вывод потока и форматирования, отображение прогресса, сообщения об ошибках и т. Д. Для того, что вы хотите сделать, вам не нужен хост PowerShell. Вы можете читать результаты выполнения скрипта с помощью класса PowerShell, проверять наличие ошибок, предупреждений, читать выходные потоки и показывать уведомление пользователю, используя возможности вашего приложения. Это будет гораздо проще и эффективнее, чем написать весь хост PowerShell, чтобы показать окно сообщения при обнаружении ошибок.
Кроме того, у объекта PowerShell есть Runspace при его создании, вам не нужно указывать его. Если вам нужно сохранить пространство выполнения для сохранения среды, просто сохраните весь объект PowerShell и очищайте Commands и все Stream каждый раз после вызова Invoke.
Следующий вопрос, который вы должны задать, заключается в том, как обработать результат PowerShell::Invoke() и прочитать PowerShell::Streams.