Передача ассоциативного массива из c # в Powershell - PullRequest
7 голосов
/ 06 марта 2009

Я бы хотел передать ассоциативный массив из C # в Powershell. В качестве примера я хотел бы выполнить эту строку кода powershell:


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

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

Я хотел бы сделать это с помощью конвейера различных команд, а не одной команды, помеченной как скрипт. Вот код:


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

Но этот ассоциативный массив, передаваемый в качестве параметра в Select-Object, не анализируется правильно. Вот что выходит на другую сторону:


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

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

Что не так с тем, как я настраиваю параметры команды Select-Object?

1 Ответ

13 голосов
/ 06 марта 2009

Создание конвейера через c # и создание конвейера со встроенным скриптом PowerShell имеют одно существенное отличие, которое на самом деле довольно неуловимо: связыватель параметров.

если я напишу версию вашего кода в чистом виде, я получу ту же ошибку: литерал хеш-таблицы обрабатывается как строковое значение.

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

В этом случае команда получает массив из двух строк: «имя» и буквенную строку хеш-таблицы. Это будет сломано точно так же, как ваш C #. Теперь взглянем на правильный способ сделать это (в сценарии) - позвольте мне переписать строку 3:

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

Так что изменилось? Я удалил кавычки вокруг хеш-таблицы - я передаю хеш-таблицу как второй элемент массива объектов! Итак, чтобы ваш пример C # работал, вам нужно сделать то, что связыватель параметров делает для нас в командной строке (что довольно много!). Заменить:

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

с

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

Надеюсь, это прояснит для вас. Связыватель параметров, вероятно, является наименее заметной, но самой мощной частью взаимодействия с PowerShell.

-Oisin

...