Захват вывода Powershell в C # после бросков Pipeline.Invoke - PullRequest
11 голосов
/ 05 августа 2009

Я запускаю тестовый скрипт Powershell из приложения C #. Сценарий может завершиться с ошибкой из-за плохого командлета, из-за которого pipe.Invoke () выдает исключение.

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

Есть ли что-то, что я пропускаю? Спасибо!

m_Runspace = RunspaceFactory.CreateRunspace();
m_Runspace.Open();
Pipeline pipe = m_Runspace.CreatePipeline();
pipe.Commands.AddScript(File.ReadAllText(ScriptFile));
pipe.Commands.Add("Out-String");
try {
   results = pipe.Invoke();
}
catch (System.Exception)
{
   m_Runspace.Close();
   // How can I get to the Powershell output that comes before the exception?
}

Ответы [ 3 ]

16 голосов
/ 06 августа 2009

Не уверен, что это полезно. Я предполагаю, что вы работаете с V1. Этот подход V2 не генерирует и печатает результат:

Hello World
67 errors

string script = @"
  'Hello World'
  ps | % {
    $_.name | out-string1
  }
";

PowerShell powerShell = PowerShell.Create();

powerShell.AddScript(script);
var results = powerShell.Invoke();

foreach (var item in results)
{
  Console.WriteLine(item);
}

if (powerShell.Streams.Error.Count > 0)
{
  Console.WriteLine("{0} errors", powerShell.Streams.Error.Count);
}
8 голосов
/ 25 сентября 2009

Решение, которое я в итоге использовал, состояло в том, чтобы реализовать наш собственный PSHost для обработки выходных данных PowerShell. Первоначальная информация для этого поступила из http://community.bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx в разделе «Создание собственного хоста PS».

В моем случае это также потребовало использования пользовательского PSHostRawUserInterface.

Вот краткий обзор того, что было сделано. Я только перечислил функцию, которую я на самом деле реализовал, но есть много, которые просто содержат throw new NotImplementedException ();

private class myPSHost : PSHost
{
   (Same as what the above link mentions)
}
private class myPSHostUI : PSHostUserInterface
{
   private myPSHostRawUI rawui = new myPSHostRawUI();

   public override void Write // all variations
   public override PSHostRawUserInterface RawUI { get { return rawui; } }

}
private class myPSHostRawUI : PSHostRawUserInterface
{
   public override ConsoleColor ForegroundColor
   public override ConsoleColor BackgroundColor
   public override Size BufferSize
}
3 голосов
/ 28 августа 2017

У меня такая же проблема. Самый простой способ получить выходные данные, когда pipe.Invoke () создает исключение, это использовать Invoke (IEnumerable input, IList output)

Пример показывает, как получить все выходные данные, ошибки, убывающие значения и т. Д. В правильном порядке

Сценарий PowerShell

Write-Output "Hello world" 
Write-Error "Some error"
Write-Warning "Some warning"
throw "Some exception"

C #

List<string> RunLog = new List<string>(); 

using (System.Management.Automation.PowerShell psInstance = System.Management.Automation.PowerShell.Create())

{
    psInstance.AddScript(_Script);

psInstance.Streams.Error.DataAdded += (sender, args) =>
{
    ErrorRecord err = ((PSDataCollection<ErrorRecord>)sender)[args.Index];
    RunLog.Add($"ERROR: {err}");
};

psInstance.Streams.Warning.DataAdded += (sender, args) =>
{
    WarningRecord warning = ((PSDataCollection<WarningRecord>)sender)[args.Index];
    RunLog.Add($"WARNING: {warning}");
};

... etc ...

var result = new PSDataCollection<PSObject>();
result.DataAdded += (sender, args) =>
{
    PSObject output = ((PSDataCollection<PSObject>)sender)[args.Index];
    RunLog.Add($"OUTPUT: {output}");
};

try
{
    psInstance.Invoke(null, result);
}
catch(Exception ex)
{
    RunLog.Add($"EXCEPTION: {ex.Message}");
}                                                
}
...