首页 文章

在ProcessRecord中停止执行cmdlet

提问于
浏览
2

如何停止执行在ProcessRecord方法中接受管道输入的cmdlet . 如果不满足ProcessRecord中的条件,我需要立即停止执行并返回 false

protected override void BeginProcessing()
{
    _output = true;
}

protected override void ProcessRecord()
{
    //processing
    if(condtion == true) return;

    _output = false;
    //How do I stop processing now, and ensure _output is returned as result?
}

protected override void EndProcessing()
{
    WriteObject(_output);
}

PipelineStoppedException 似乎有效,但并没有给我确切的行为 .

使用 PipelineStoppedException 更新了一个更具体的示例:

让我们考虑一个cmdlet First-List ,它应该与LINQ中的 First() 类似 . 此cmdlet的实现如下:

[Cmdlet("First", "List")]
public class FirstList : Cmdlet
{
    [Parameter(Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
    public object Input { get; set; }

    [Parameter(Position = 0, Mandatory = true)]
    public ScriptBlock ScriptBlock { get; set; }

    protected override void ProcessRecord()
    {
        var output = ScriptBlock.InvokeWithContext(null, new List<PSVariable>
        {
            new PSVariable("input", Input),
        })[0];

        if (output.ToString() != "True") return;

        WriteObject(Input);
        throw new PipelineStoppedException();
    }

    protected override void EndProcessing()
    {
        Error.NoMatch();
    }
}

使用 Select -First ,我可以执行以下操作:

$a = 1..10 | Select -First 1
#$a is 1

但随着我的实施:

$a = 1..10 | First-List { $input -ge 5 }
#$a should be assigned 5, but it is not

1..10 | First-List { $input -ge 5 } 确实输出了5 .

更新2:

似乎 Select-Object 实际上抛出了 StopUpstreamCommandsException .

还有一个反馈可以在这里提供 - https://connect.microsoft.com/PowerShell/feedback/details/768650/enable-users-to-stop-pipeline-making-stopupstreamcommandsexception-public

3 回答

  • 1

    我通过抛出 StopUpstreamCommandsException 获得了 Select -First 的行为 . 但由于它是 System.Management.Automation 的内部,不得不使用反射 . 写了一个如下所示的实用方法:

    internal static class Error
    {
        private static readonly Type StopUpstreamCommandsExceptionType =
            Assembly.GetAssembly(typeof (PSCmdlet))
                .GetType("System.Management.Automation.StopUpstreamCommandsException");
    
        internal static Exception StopUpstreamCommandsException(Cmdlet cmdlet)
        {
            var stopUpstreamCommandsException = (Exception) Activator.CreateInstance(StopUpstreamCommandsExceptionType,
                BindingFlags.Default | BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public,
                null,
                new Object[] {(InternalCommand) cmdlet},
                null
                );
            return stopUpstreamCommandsException;
        }
    }
    
  • 4

    目前不在我的开发机器上 . 抛出 System.Management.Automation.PipelineStoppedException 会有用吗?

  • 1

    许多内置cmdlet在想要暂停正在运行的管道时抛出System.Management.Automation.PipelineStoppedException . 例如,这就是select-object -first N的工作原理 . 你试过吗?

相关问题