Pregunta

Me gustaría pasar una matriz asociativa de C # a Powershell. Como ejemplo, me gustaría ejecutar esta línea de código de 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 Canal de comandos distintos 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 esa matriz asociativa que se pasa como parámetro a Select-Object no se analiza correctamente. Esto es lo que sale por el 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 Seleccionar-Objeto?

¿Fue útil?

Solución

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

si escribo una versión de tu código en un script puro, obtendré el mismo error: el literal de 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 una matriz de dos cadenas, el " nombre " y la cadena literal hashtable. Esto se romperá exactamente de la misma manera que su C #. Ahora, eche un vistazo a la forma correcta de hacerlo (en secuencia de comandos). Permítame reescribir la línea 3:

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

Entonces, ¿qué cambió? Eliminé las comillas alrededor de la tabla hash. ¡Estoy pasando una tabla hash como el segundo elemento de la matriz de objetos! Por lo tanto, para hacer que su ejemplo de C # funcione, debe hacer lo que la carpeta de parámetros hace por nosotros en la línea de comandos (¡lo cual 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 se aclare para ti. La carpeta de parámetros es probablemente la parte menos visible pero más poderosa de la experiencia de powershell.

-Oisin

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top