Passer un tableau associatif de c # à Powershell
-
03-07-2019 - |
Question
J'aimerais passer un tableau associatif de C # à Powershell. A titre d'exemple, j'aimerais exécuter cette ligne de code powershell:
PS C:\> get-command | select name, @{N="Foo";E={"Bar"}} -first 3
Name Foo
---- ---
Add-Content Bar
Add-History Bar
Add-Member Bar
Je souhaite le faire via un pipeline de commandes distinctes , par opposition à une commande unique marquée en tant que script. Voici le code:
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());
Mais ce tableau associatif transmis en tant que paramètre à Select-Object n’est pas analysé correctement. C’est ce qui ressort de l’autre côté:
PS C:\test> c:\test\Bin\Debug\test.exe
Name @{N="Foo";E={"Bar"}}
---- --------------------
Add-Content
Add-History
Add-Member
Quel est le problème avec la configuration des paramètres de la commande Select-Object?
La solution
La création d'un pipeline via C # et la création d'un pipeline avec un script natif PowerShell présentent une différence majeure qui est en réalité assez subtile: le classeur de paramètres.
si j'écris une version de votre code en script pur, j'obtiens la même erreur: le littéral hashtable est traité comme une valeur de chaîne.
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"}}'))
Dans ce cas, la commande reçoit un tableau de deux chaînes, le "nom". et la chaîne littérale hashtable. Cela sera cassé exactement de la même manière que votre C #. Maintenant, jetez un oeil à la bonne façon de le faire (dans le script) - laissez-moi réécrire la ligne 3:
ps> $ps.Commands[1].Parameters.Add("Property", @("Name", @{N="Foo";E={"Bar"}}))
Alors qu'est-ce qui a changé? J'ai supprimé les guillemets autour de la table de hachage - je passe une table de hachage en tant que deuxième élément du tableau d'objets! Donc, pour que votre exemple C # fonctionne, vous devez faire ce que le classeur de paramètres fait pour nous en ligne de commande (ce qui est tout un tas!). Remplacer:
properties.Add("@{N=\"Foo\";E={\"Bar\"}}");
avec
properties.Add(
new Hashtable {
{"N", "Foo"},
{"E", System.Mananagement.Automation.ScriptBlock.Create("\"Foo\"")}
}
);
J'espère que cela vous éclaircit. Le paramètre binder est probablement la partie la moins visible mais la plus puissante de l’expérience de powershell.
-Oisine