2009-03-06 24 views
7

Vorrei passare un array associativo da C# a Powershell. Come esempio Vorrei eseguire questa linea powershell di codice:Passaggio di un array associativo da C# a Powershell


PS C:\> get-command | select name, @{N="Foo";E={"Bar"}} -first 3 

Name              Foo 
----              --- 
Add-Content             Bar 
Add-History             Bar 
Add-Member             Bar 

mi vuoi fare questo attraverso una pipeline di distinti Comandi anziché un singolo comando contrassegnata come script. Ecco il codice:


Runspace runspace = RunspaceFactory.CreateRunspace(); 
runspace.Open(); 
Pipeline pipeline = runspace.CreatePipeline(); 

pipeline.Commands.Add("get-command"); 

Command c = new Command("select-object"); 
List properties = new List(); 
properties.Add("name"); 
properties.Add("@{N=\"Foo\";E={\"Bar\"}}"); 
c.Parameters.Add("Property", properties.ToArray()); 
c.Parameters.Add("First", 3); 
pipeline.Commands.Add(c); 

pipeline.Commands.Add("Out-String"); 

Collection retval = pipeline.Invoke(); 
runspace.Close(); 

StringBuilder stringBuilder = new StringBuilder(); 
foreach (PSObject obj in retval) 
    Console.WriteLine(obj.ToString()); 

Ma questo array associativo viene passata come parametro a Select-Object non viene analizzato correttamente. Questo è ciò che viene fuori l'altro lato:


PS C:\test> c:\test\Bin\Debug\test.exe 

Name          @{N="Foo";E={"Bar"}} 
----          -------------------- 
Add-Content 
Add-History 
Add-Member 

Cosa c'è di sbagliato con il modo Sto installando i parametri di comando Select-Object?

risposta

13

La creazione di una pipeline tramite C# e la creazione di una pipeline con script PowerShell nativo presentano una differenza importante che è in realtà piuttosto sottile: il parametro binder.

se scrivo una versione del tuo codice in puro script, otterrò lo stesso errore: il valore letterale hashtable è trattato come un valore stringa.

ps> $ps = $ps.Commands.Add("get-process") 
ps> $ps = $ps.Commands.Add("select-object") 
ps> $ps.Commands[1].Parameters.Add("Property", @("Name", '@{N="Foo";E={"Bar"}}')) 

In questo caso, il comando riceve un array di due stringhe, il "nome" e la stringa letterale tabella hash. Questo sarà rotto esattamente nello stesso modo del tuo C#. Ora, date un'occhiata al il modo giusto per farlo (in caratteri) - mi permetta di riscrivere la linea 3:

ps> $ps.Commands[1].Parameters.Add("Property", @("Name", @{N="Foo";E={"Bar"}})) 

Allora, cosa è cambiato? Ho rimosso le virgolette attorno alla tabella hash - sto passando una tabella hash come secondo elemento dell'array di oggetti! Quindi, per far funzionare il tuo esempio in C#, devi fare ciò che il binder dei parametri fa per noi alla riga di comando (che è parecchio!). Sostituisci:

properties.Add("@{N=\"Foo\";E={\"Bar\"}}"); 

con

properties.Add(
    new Hashtable { 
     {"N", "Foo"}, 
     {"E", System.Mananagement.Automation.ScriptBlock.Create("\"Foo\"")} 
    } 
); 

Spero che questo libera per voi. Il parametro binder è probabilmente la parte meno visibile ma più potente dell'esperienza di PowerShell.

-Oisin

+0

tipo su 'Mananagement', anche "l'errore CS0117: 'System.Management.Automation.ScriptBlock' non contiene una definizione per 'Crea'" - a parte questo, funziona alla grande – xcud

+0

ah, devi usare v1 powershell (il creare statico è su v2). scusa! – x0n

+0

Questo è quello che ho capito. Soluzione accettata comunque. Ho adattato ciò che hai fornito per ottenere ciò di cui avevo bisogno e l'ho applicato alla vera app. Funziona alla grande. Il migliore di sempre. – xcud

Problemi correlati