Вызовите блоки сценариев из C # с помощью оперативного вывода

#c# #powershell

#c# #powershell

Вопрос:

Я хочу написать определение типа класса внутри модуля PowerShell. Этот содержит список, который содержит scriptblocks и некоторые другие переменные. Также в нем есть функция для вызова всех доступных scriptblocks в его списке.

Чтобы вызвать scriptblock, я попробовал несколько подходов и остановился на самом простом, например:

 Powershell psinstance = PowerShell.Create()
psinstance.AddScript("bla bla bla")
psinstance.Invoke()
  

Пока это работает нормально, но у меня есть тонкая деталь, которую я хочу иметь.

Этот вызов просто возвращает результат после того, как он был полностью завершен.

Для конкретного примера давайте используем другой scriptblock, который лучше всего описывает эту проблему. Сначала из PowerShell напрямую:

 $a = { ping 127.0.0.1 }
  

если вы запустите этот с

 amp; $a
  

или

 Invoke-Expression $a
  

вы получите построчный вывод напрямую. Таким образом, при отправке первого запроса вы получите первую строку, при отправке второго запроса вы получите вторую строку и так далее.

Но если вы сделаете

 $a.Invoke()
  

вы получите полные результаты только после отправки 4 запросов, вообще через 4 секунды. Или, если бы вы использовали t-аргумент, он выполнялся бы вечно без вывода вообще.

Та же «проблема», которую я получаю, если я вызываю этот скриптовый блок через код C #

Но я хочу, чтобы поведение, которое я получал бы при использовании оператора вызова или Invoke-Expression изнутри PowerShell.

Как мне получить оперативный вывод на мою консоль?

Я также был бы счастлив, если бы знал, что именно делает оператор amp; (или Invoke-Expression ) в .Чистый фон.

Но, возможно, это просто то, чего я не вижу в ATM. Кто-нибудь знает?

Ответ №1:

команда invoke позволяет добавить параметр для вывода (IList). если вы используете observablecollection в качестве выходного параметра и подключаетесь к событию CollectionChanged, то вы можете записать выходные данные на свою консоль:

 var psinstance = System.Management.Automation.PowerShell.Create();
psinstance.AddScript("ping 127.0.0.1");

var output = new System.Collections.ObjectModel.ObservableCollection<string>();
output.CollectionChanged  = (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) =>
{
    foreach(var item in e.NewItems)
        Console.WriteLine(item);
};
psinstance.Invoke(null, output);
  

Комментарии:

1. Я попробовал это в демо-проекте, и это сработало очень хорошо. Я включу это в свой основной проект, где я удалю использование класса Process. До сих пор я думаю, что это должно быть помечено как ответ на вопрос