2009-03-06 20 views
7

Me gustaría pasar una matriz asociativa de C# a Powershell. A modo de ejemplo me gustaría ejecutar esta línea de PowerShell de código:Pasar una matriz asociativa de 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 

me gustaría hacer esto a través de un gasoducto de distintas comandos en lugar de un solo comando marcado como una secuencia de comandos. Aquí está el código:


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()); 

Pero eso matriz asociativa que se pasa como un parámetro para seleccionar a objetos no se analiza correctamente. Esto es lo que sale del otro lado:


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

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

¿Qué hay de malo en cómo estoy configurando los parámetros del comando Select-Object?

Respuesta

13

La creación de una canalización a través de C# y la creación de una canalización con script nativo de powershell tienen una diferencia importante que en realidad es bastante sutil: la carpeta del parámetro.

si escribo una versión de su código en script puro, obtendré el mismo error: el literal de la tabla hash se trata como un valor de cadena.

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"}}')) 

En este caso, el comando recibe un conjunto de dos cuerdas, el "nombre" y la cadena literal tabla hash. Esto se romperá exactamente de la misma manera que su C#. Ahora, echar un vistazo a la forma correcta de hacerlo (en escritura) - déjame volver a escribir la línea 3:

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

Entonces, ¿qué ha cambiado? Eliminé las comillas alrededor de la tabla hash. ¡Estoy pasando una hashtable como el segundo elemento de la matriz de objetos! Entonces, para que funcione su ejemplo de C#, debe hacer lo que el encuadernador de parámetros hace por nosotros en la línea de comandos (¡que es bastante!). Reemplazar:

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

con

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

Espero que esto aclare para arriba para usted. El enlazador de parámetros es probablemente la parte menos visible pero más poderosa de la experiencia de PowerShell.

-Oisin

+0

tipo de 'Mananagement', también "CS0117 de error: 'System.Management.Automation.ScriptBlock' no contiene una definición para 'Crear'" - aparte de eso, funciona muy bien – xcud

+0

ah, debe usar v1 powershell (la creación estática está en v2). ¡lo siento! – x0n

+0

Eso es lo que pensé. Solución aceptada de todos modos. Adapté lo que me proporcionó para obtener lo que necesitaba y lo apliqué a la aplicación real. Funciona genial. Mejor que nunca – xcud

Cuestiones relacionadas