如何输入字符串列表作为参数?

时间:2018-09-02 08:12:04

标签: powershell parameters

我有一个cmdlet,我在其中接受字符串列表作为参数,该字符串在c#类中定义如下:

[Parameter(Mandatory = true)]
public List<string> AllowedScopes;

因此,当我调用名为Add-Client的命令时,如何在PowerPhell中提供字符串列表?我已经尝试过了(每行是一种不同的方法):

-AllowedScopes scope1, scope2, scope3
-AllowedScopes [scope1, scope2, scope3]
-AllowedScopes {scope1, scope2, scope3}
-AllowedScopes {"scope1", "scope2", "scope3"}

但是我总是只在列表“ AllowedScopes”中获得一个条目,其中包含在AllowedScopes参数名称之后输入的完整字符串。

我对此一无所获,所以我想我问错了问题。

我当然可以将AllowedScopes参数设置为简单的字符串,然后执行以下操作:

var AllowedScopesAsList = this.AllowedScopes.Split(',').ToList();

但是我认为这应该是powershell提供的(因为它提供了许多其他有用的功能,使我无法实现cmdlet的整个用户交互部分)

编辑:这是我的cmdlet C#类的全部内容:

using System.Collections.Generic;
using System.Management.Automation;

namespace MyCmdlets
{
    [Cmdlet("Add", "Client")]
    public class AddClient : Cmdlet
    {
        [Parameter(Mandatory = true)]
        public List<string> AllowedScopes;

        protected override void ProcessRecord()
        {
            AllowedScopes.ForEach(a => WriteObject(a));
        }
    }
}

有了这个,如果我尝试像回答之一那样输入列表:

Add-Client -AllowedScopes @('scope1', 'scope2')

我得到以下输出:

<pre>
scope1
scope2
</pre>

符合预期。

但是,如果我在PowerShell询问时提供参数,则无法使用它,如下所示:

<pre>
PS> <b>Add-Client</b> <kbd>Enter</kbd>

Cmdlet Add-Client at CommandPipelineposition 1
Enter the values for the following parameter:
AllowedScopes[0]: <b>@('scope1','scope2')</b> <kbd>Enter</kbd>
AllowedScopes[1]: <kbd>Enter</kbd>
</pre>

现在的输出是这样:

@('scope1','scope2')

即使我在其中一一输入范围,它仍然会导致列表仅接收一个孩子:

<pre>
AllowedScopes[0]: <b>'scope1'</b>
AllowedScopes[1]: <b>'scope2'</b>
AllowedScopes[2]:
</pre>

输出:

<pre>
'scope1' 'scope2'
</pre>

/ edit2: 我上传了一个视频,因此您可以了解Powershell的行为是否与预期不符(至少我认为不这样):

Youtube-Video with powershell-misbehavior

2 个答案:

答案 0 :(得分:5)

您似乎遇到了 bug ,这会影响Windows PowerShell(从v5.1开始)和PowerShell Core(从v6.1.0开始)

PowerShell的自动提示意外地将单独输入的元素作为单个字符串绑定到参数-AllowedScopes,该字符串是单个元素的串联,并用空格分隔。
相比之下,从命令行传递值数组-例如,
-AllowedScopes scope1, scope2, scope3-正常工作。

错误是由您将参数定义为List<string> 而不是string[]触发的。 可以说,在这种情况下,string[]还是更好的选择,因此解决方法是将-AllowedScopes参数声明为string[](数组)

Add-Type -TypeDefinition @'
using System.Collections.Generic;
using System.Management.Automation;

namespace MyCmdlets
{
    [Cmdlet("Add", "Client")]
    public class AddClient : Cmdlet
    {
        [Parameter(Mandatory = true)]
        // Use string[] instead of List<string>
        public string[] AllowedScopes;

        protected override void ProcessRecord()
        {
            foreach (var scope in AllowedScopes) {
                WriteObject(scope);
            }
        }
    }
}
'@ -PassThru | ForEach-Object Assembly | Import-Module

# Let PowerShell prompt for -AllowedScopes
# Due to use of string[] rather than List<string>, the individually entered
# elements are now correctly passed as an array.
Add-Client 

请注意,如果将string以外的类型用于通用列表,则错误不会出现。


带有一般信息的原始答案

您的代码按设计工作,-AllowedScopes scope1, scope2, scope3确实是传递多个列表元素的方式:

scope1, scope2, scope3使用数组构造运算符,构造一个3元素数组,该数组绑定到-AllowedScopes参数并转换为List<string>实例。

PowerShell的强制性参数自动提示机制(在命令行上未传递任何参数)也按设计工作:

对于集合类型的参数,例如-AllowedScopes

  • 分别提示集合中的元素
  • 提交最后一个元素后,再按一次 Enter ,即可表示输入结束。

如果要允许用户使用单个提示符传递所有元素,则必须实现自定义逻辑:

  • -AllowedScopes声明为单个字符串,以便用户可以传递类似
    'scope1, scope2, scope3'

  • 将接收到的字符串值拆分为cmdlet内的嵌入式元素。

答案 1 :(得分:0)

尝试-AllowedScopes @('scope1', 'scope2', 'scope3')

@构造表示一个数组,因此@(item,item,item,..)组成一个值数组。