我想将一个关联数组从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

我想通过 distinct 命令的管道来执行此操作,而不是标记为脚本的单个命令。这是代码:


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命令参数有什么问题?

有帮助吗?

解决方案

通过c#创建管道并使用native PowerShell脚本创建管道有一个主要区别,实际上非常微妙:参数binder。

如果我在纯脚本中编写代码版本,我将得到相同的错误:哈希表文字被视为字符串值。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top