2009-08-05 4 views
11

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

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

Есть ли что-то, что мне не хватает? Благодаря!

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? 
} 

ответ

8

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

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

Вот краткий обзор того, что было сделано. Я только перечислил функцию, на которой я фактически повлиял, но есть много, которые просто содержат бросок нового 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 
} 
+0

Хороший, именно то, что я искал. Благодарю. –

14

Не уверен, что это полезно. Я предполагаю, что вы используете 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); 
} 
+0

Вы правильно, я использую питания оболочка v1. –

0

У меня такая же проблема. Самый простой способ получить выход при 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}"); 
}             
}