Domanda

Vorrei passare un array associativo da C # a Powershell. Ad esempio, vorrei eseguire questa riga di codice PowerShell:


PS C:\> get-command | select name, @{N="Foo";E={"Bar"}} -first 3

Name                                                        Foo
----                                                        ---
Add-Content                                                 Bar
Add-History                                                 Bar
Add-Member                                                  Bar

Mi piacerebbe farlo tramite una pipeline di comandi distinti invece di un singolo comando contrassegnato come uno script. Ecco il codice:


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

Ma quell'array associativo passato come parametro a Select-Object non viene analizzato correttamente. Questo è ciò che emerge dall'altra parte:


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

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

Cosa c'è che non va nel modo in cui sto impostando i parametri del comando Select-Object?

È stato utile?

Soluzione

La creazione di una pipeline tramite c # e la creazione di una pipeline con script PowerShell nativo presentano un'importante differenza che in realtà è piuttosto sottile: il raccoglitore di parametri.

se scrivo una versione del tuo codice in puro script, otterrò lo stesso errore: il valore letterale hashtable viene trattato come un valore di stringa.

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

In questo caso, il comando riceve un array di due stringhe, il "nome" " e la stringa letterale hashtable. Questo sarà rotto esattamente allo stesso modo del tuo C #. Ora, dai un'occhiata al modo giusto di farlo (nello script) - fammi riscrivere la riga 3:

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

Quindi cosa è cambiato? Ho rimosso le virgolette intorno alla tabella hash - Sto passando una tabella hash come secondo elemento dell'array di oggetti! Quindi, per far funzionare il tuo esempio C #, devi fare ciò che il raccoglitore di parametri fa per noi dalla riga di comando (che è abbastanza!). Sostituire:

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

con

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

Spero che questo ti chiarisca. Il raccoglitore di parametri è probabilmente la parte meno visibile ma più potente dell'esperienza PowerShell.

-Oisin

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top