2012-11-06 20 views
5

Sto usando System.Management.Automation DLL che mi permette di chiamare PowerShell all'interno della mia C# applicazione in questo modo:Calling PowerShell da C#

PowerShell.Create().AddScript("Get-Process").Invoke(); 

Quello che sto cercando di fare è chiamare PowerShell, ma fornire la lista di input. Per esempio, in:

1, 2, 3 | ForEach-Object { $_ * 2 } 

Sto cercando di fornire il lato sinistro 1, 2, 3 quando si richiama:

// powershell is a PowerShell Object 
powershell.Invoke(new [] { 1, 2, 3 }); 

Tuttavia questo non funziona. Il soluzione mi è venuta stava usando ForEach-Object e poi passando la matrice come InputObject con la { $_ } come Process:

// create powershell object 
var powershell = PowerShell.Create(); 

// input array 1, 2, 3 
Command inputCmd = new Command("ForEach-Object"); 
inputCmd.Parameters.Add("InputObject", new [] { 1, 2, 3 }); 
inputCmd.Parameters.Add("Process", ScriptBlock.Create("$_")); 
powershell.Commands.AddCommand(inputCmd); 

// ForEach-Object { $_ * 2 } 
Command outputCmd = new Command("ForEach-Object"); 
outputCmd.Parameters.Add("Process", ScriptBlock.Create("$_ * 2")); 
powershell.Commands.AddCommand(outputCmd); 

// invoke 
var result = powershell.Invoke(); 

Sebbene il codice precedente funziona esiste un modo di usare Invoke passando l'ingresso array perché avrei pensato che questo sarebbe un modo desiderabile di chiamarlo?

risposta

8

Un po 'in ritardo, ma:

    PowerShell ps = PowerShell.Create(); 
    ps.Runspace.SessionStateProxy.SetVariable("a", new int[] { 1, 2, 3 }); 
    ps.AddScript("$a"); 
    ps.AddCommand("foreach-object"); 
    ps.AddParameter("process", ScriptBlock.Create("$_ * 2")); 
    Collection<PSObject> result = ps.Invoke(); 
    foreach (PSObject result in results) 
       { 
        Console.WriteLine(result); 
       } 

rendimenti exactely:

2 
4 
6 
+0

Funziona ma passi '1,2,3' come una stringa piuttosto che una matrice i.e.' new int [] {1,2,3} '. Il secondo è necessario se devo passare i dati strutturati alla pipeline. –

+0

@TahirHassan L'unico modo che conosco per passare .net oggetto creato sta usando 'SessionStateProxy.SetVariable (nome stringa, valore oggetto)'. Guarda la mia risposta modificata. –

+0

Hai risposto alla mia domanda su come avviare la pipeline con un array (senza passarlo a 'ForEach-Object' usando il parametro' InputObject' come descritto nella mia domanda). Grazie. –

2

Ho effettuato la mia ricerca e PowerShell.Invoke(IEnumerable) imposterà il InputObject del primo comando nell'elenco. Pertanto, invece di impostare InputObject su inputCmd sopra, possiamo invece passarlo attraverso il metodo Invoke. Abbiamo ancora bisogno della prima chiamata ForEach-Object per passare l'array di input a.

+0

dare una prova di mia risposta. –

+0

Questo è genio! Non lo cercherei mai lì! – t3chb0t