Как выполнить сценарии в оболочке powershell, созданной с помощью кода, в которой есть команды Write-Host?

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

После попытки нескольких различных методов (с небольшим успехом из-за ограничений с Start-Job и другие вещи) текущая реализация опирается на предварительное создание пула "оболочек" powershell, созданных с помощью $shell = [Powershell]::Create(),

Один из методов модуля, который мне нужно вызвать для начальной загрузки оболочки (так что она находится в правильном состоянии), имеет вызов Write-Host в этом. Когда я звоню $shell.Invoke() возникает следующая ошибка:

Write-Host: команда, которая запрашивает у пользователя ошибку, потому что хост-программа или тип команды не поддерживают взаимодействие с пользователем. Попробуйте хост-программу, которая поддерживает взаимодействие с пользователем, такую ​​как Windows PowerShell Console или Windows PowerShell ISE, и удалите связанные с приглашением команды из типов команд, которые не поддерживают взаимодействие с пользователем, таких как рабочие процессы Windows PowerShell.

Теперь, поскольку модуль настроен, я могу удалить Write-Host звонки, но это уменьшает удобство для пользователя, когда он запускается непосредственно конечными пользователями. Я могу создать switch параметр, который не выполняет Write-Host, если параметр имеет значение true, но сделать это по ходу дела - хорошая работа (выполнимо, но я бы предпочел, чтобы этого не было).

Есть ли способ, которым я могу получить Write-Host не ошибиться в этом сценарии? Я на самом деле не забочусь о входных данных в этом сценарии, я просто не хочу ошибок.

4 ответа

Решение

Самый быстрый способ заставить это работать - определить пустышку write-host функция в вашем скрипте, или просто определить его в пространстве выполнения независимо перед запуском вашего скрипта.

$ps.addscript("function write-host {}").invoke()
$ps.commands.clear()
# now you can invoke scripts that use write-host
# feel free to implement a write-host that writes to a log file

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

Если вам нужен вывод, вы можете использовать:

$ps.addscript("function write-host($out) {write-output $out}").invoke()
$ps.commands.clear()

Если вы хотите продолжать использовать класс Pipeline, вы можете использоватьCommand.MergeMyResults[метод][1]. Например, чтобы перенаправить потоки всех типов на вывод конвейера:

      private string RunScript(string scriptText) {

    Runspace runspace = RunspaceFactory.CreateRunspace();

    runspace.Open();

    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript("Write-Host Test");
    pipeline.Commands[pipeline.Commands.Count-1]
       .MergeMyResults(PipelineResultTypes.All, PipelineResultTypes.Output)
    
    Collection < PSObject > results = pipeline.Invoke();

    runspace.Close();

    foreach(PSObject obj in results) {
        Console.WriteLine(obj.ToString());
    }
}

Попробуйте изменить версию WMF на 5.1 - https://www.microsoft.com/en-us/download/details.aspx?id=54616

Другие вопросы по тегам