2009-08-05 9 views
11

Sto eseguendo uno script di test Powershell da un'applicazione C#. Lo script può fallire a causa di un cattivo cmdlet che provoca pipe.Invoke() per generare un'eccezione.Acquisizione di output Powershell in C# dopo Pipeline.Invoke genera

Sono in grado di acquisire tutte le informazioni necessarie sull'eccezione, ma mi piacerebbe poter visualizzare l'output dello script fino a quel punto. Non ho avuto fortuna perché i risultati sembrano essere nulli quando viene lanciata un'eccezione.

C'è qualcosa che mi manca? Grazie!

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

risposta

8

La soluzione che ho finito per usare è stato quello di implementare il nostro PSHost per gestire l'output di PowerShell. Le informazioni iniziali a riguardo sono state fornite da http://community.bartdesmet.net/blogs/bart/archive/2008/07/06/windows-powershell-through-ironruby-writing-a-custom-pshost.aspx nella sezione "Creazione di un host PS personalizzato".

Nel mio caso ha richiesto anche l'utilizzo di una PSHostRawUserInterface personalizzata.

Ecco la rapida panoramica di ciò che è stato fatto. Ho solo elencato la funzione che ho effettivamente implorato, ma ce ne sono molte che contengono solo nuove 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

Bello, esattamente quello che stavo cercando. Grazie. –

14

Non sicuro se questo è utile. Sto indovinando che stai eseguendo V1. Questo approccio V2 non genera e stampa il risultato:

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

lei ha ragione, sto usando Potenza shell v1. –

0

Ho lo stesso problema. Il modo più semplice per ottenere output quando pipe.Invoke() genera un'eccezione è quello di utilizzare Invoke(IEnumerable input, IList output)

esempio mostra come ottenere tutto l'output, errore, ecc calante nel giusto ordine

script di 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}"); 
}             
}