2009-08-05 9 views
11

Używam skryptu testowego PowerShell z aplikacji C#. Skrypt może się nie powieść z powodu złego polecenia cmdlet, które powoduje, że pipe.Invoke() zgłasza wyjątek.Przechwytywanie danych wyjściowych powłoki Powderhell w języku C# po potoku Pipeline.Invoke

Jestem w stanie zebrać wszystkie informacje, których potrzebuję o wyjątku, ale chciałbym móc wyświetlić wyniki skryptu do tego momentu. Nie miałem szczęścia, ponieważ wyniki okazały się zerowe, gdy został zgłoszony wyjątek.

Czy jest coś, czego mi brakuje? Dzięki!

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

Odpowiedz

8

Rozwiązanie skończyło się używając było wdrożenie własnej PSHost obsługiwać wyjście PowerShell jest. Początkowe informacje na ten temat pochodzą z sekcji http://community.bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx w sekcji "Budowanie niestandardowego hosta PS".

W moim przypadku wymagało to również użycia niestandardowego interfejsu PSHostRawUserInterface.

Oto krótki przegląd tego, co zostało zrobione. Wymieniłem tylko funkcję, którą faktycznie wprowadziłem w życie, ale jest wiele takich, które zawierają tylko nową funkcję 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

Niezły, dokładnie tego, czego szukałem. Dzięki. –

14

Nie jestem pewien, czy to jest pomocne. Zgaduję, że używasz V1. Takie podejście V2 nie rzucać i drukuje wynik:

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

masz rację, używam zasilania shell v1. –

0

Mam ten sam problem. Najprostszym sposobem, aby uzyskać wyjście kiedy pipe.Invoke() wyrzuca wyjątek jest użycie Invoke(IEnumerable input, IList output)

przykład pokazuje, jak uzyskać wszystkie wyjścia, błąd, itp słabnie we właściwej kolejności

skrypt 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}"); 
}             
} 
Powiązane problemy