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?

Était-ce utile?

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top