假设您有两个 Cmdlet:第一个返回输出,第二个使用该输出作为输入参数。
public class Cmdlet1 : PSCmdlet
{
protected override void ProcessRecord()
{
List<string> result = ...
WriteObject(result, true);
}
}
public class Cmdlet2 : PSCmdlet
{
[Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true)]
public string Input { get; set; }
protected override void ProcessRecord()
{
// Do a long operation on Input.
}
}
Cmdlet2 将以这种方式被调用多次(对于 Cmdlet1 返回的 IEnumerable 中的每个元素一次),您可以很好地将它们通过管道连接在一起:选择对象-前 10 | Cmdlet2 只有 Cmdlet1 输出的前 10 个元素被发送到 Cmdlet2。
因为 Cmdlet2 需要一些时间,所以显示进度会很好。目前我们不能这样做,因为我们只能一一接收输入字符串。我们把 Cmdlet2 的输入改成 List
public class Cmdlet1 : PSCmdlet
{
protected override void ProcessRecord()
{
List<string> result = ...
WriteObject(result, true);
}
}
public class Cmdlet2 : PSCmdlet
{
[Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true)]
public List<string> Input { get; set; }
protected override void ProcessRecord()
{
// Do a long operation on Input.
}
}
我们仍然一一获取输入字符串,因为 Cmdlet1 中的 WriteObject 调用具有 true 作为第二个参数,允许 PowerShell 将结果枚举到单个对象。如果我们将其更改为 false,PowerShell 不会枚举结果,并且 Cmdlet2 会获取整个字符串列表作为输入,我们可以对所有字符串进行操作并显示一个漂亮的进度条。
public class Cmdlet1 : PSCmdlet
{
protected override void ProcessRecord()
{
List<string> result = ...
WriteObject(result, false);
}
}
public class Cmdlet2 : PSCmdlet
{
[Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true)]
public List<string> Input { get; set; }
protected override void ProcessRecord()
{
// Do a long operation on Input, displaying a progress bar.
}
}
但是:现在我们不能再轻易地管它们了。Cmdlet1 | 选择对象-前 10 | Cmdlet2 现在将整个输入发送到 Cmdlet2!Select-Object 不采用前 10 个,因为只有 1 个元素是 IEnumerable,并且该元素完全发送到 Cmdlet2!
处理这种情况的正确方法是什么?