停止ProcessRecord中cmdlet的执行
本文关键字:执行 cmdlet ProcessRecord 停止 | 更新日期: 2023-09-27 18:18:14
如何停止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。
似乎Select-Object
实际上抛出了StopUpstreamCommandsException
。
也有一个反馈在这里提供- https://connect.microsoft.com/PowerShell/feedback/details/768650/enable-users-to-stop-pipeline-making-stopupstreamcommandsexception-public
我通过抛出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;
}
}
目前不在我的开发机器上。如果你抛出一个System.Management.Automation.PipelineStoppedException
,它会工作吗?
许多内置的cmdlet在想要停止正在运行的管道时抛出System.Management.Automation.PipelineStoppedException异常。例如,这就是select-object -first N的工作原理。你试过吗?