Pasando una matriz asociativa de c # a Powershell
-
03-07-2019 - |
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?
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