【问题标题】:Stopping PowerShell pipeline, ensure end is called停止 PowerShell 管道,确保调用 end
【发布时间】:2016-01-28 13:14:14
【问题描述】:

我想要做的是获得一个功能来在达到时间限制时停止管道馈送。我创建了一个测试函数如下:

function Test-PipelineStuff
{
    [cmdletbinding()]
    Param(
        [Parameter(ValueFromPipeLIne=$true)][int]$Foo,
        [Parameter(ValueFromPipeLIne=$true)][int]$MaxMins
    )

    begin { 
        "THE START" 
        $StartTime = Get-Date
        $StopTime = (get-date).AddMinutes($MaxMins)
        "Stop time is: $StopTime"
    } 

    process 
    {  
        $currTime = Get-Date
        if( $currTime -lt $StopTime ){
            "Processing $Foo"            
        }
        else{
            continue;
        }
    }

    end { "THE END" }
}

这肯定会停止管道,但它永远不会调用我的“end{}”块,在这种情况下,它是至关重要的。有谁知道为什么当我使用“继续”停止管道时没有调用我的“结束{}”块?如果我抛出 PipelineStoppedException,行为似乎是相同的。

【问题讨论】:

  • 大概continue 正在跳出它的包含循环,只是没有一个,所以它跳出了你的整个函数。不过,这并不完全有帮助。我不确定是否有合适的方法来做你想做的事情。
  • 据我了解,诸如 Select-Object -First 1 之类的 cmdlet 将引发 StopUpstreamCommandsException 以停止管道,这是一个内部异常,对我自己的使用不可见。 :(
  • 也许将您的end{} 处理放入一个不同的脚本块中,您可以从process{} 中的else{} 子句调用它?
  • Pipeline.Stop 方法似乎也很有用,但我有限的 powershell 知识意味​​着我无法弄清楚如何在快速测试中使其工作。
  • 发现了一些类似的问题,可能值得看一下stackoverflow.com/questions/28522507/…

标签: powershell pipeline powershell-4.0


【解决方案1】:

根据about_Functions

函数接收到管道中的所有对象后,End 语句列表运行一次。如果没有 Begin、Process 或 End 关键字 被使用时,所有的语句都被视为一个 End 语句列表。

因此,您只需省略 else 块。然后处理管道中的所有对象,但由于if 子句,实际处理仅在达到时间限制之前完成。

【讨论】:

  • 如果我必须等待它处理管道中的所有对象,它几乎否定了试图告诉它在某个时间停止的好处。我试图让这个脚本在达到时间限制时停止,并避免处理超出该限制的所有项目。当然,如果我处理所有内容,我可以让结束块执行,但这不是我的目标。
  • 问题是,为什么 end 块永远不会被调用。答案是,只有在处理完管道中的所有项目后才会调用它。
  • 不,问题是我如何停止管道并确保调用结束。
【解决方案2】:

使用break / continue 或抛出异常总是会过早退出您的函数(并且还会中断/继续任何封闭循环)。

但是,您可以在 begin 块中嵌入一个清理函数,该函数实现您最初放入 end 块的内容,并从 both 您的 process 块中调用该函数 - 只需continue 之前 - end 块:

function Test-PipelineStuff
{
    [cmdletbinding()]
    Param(
        [Parameter(ValueFromPipeLine=$true)][int]$Foo,
        [Parameter(ValueFromPipeLine=$true)][int]$MaxMins
    )

    begin { 
        "THE START" 
        $StartTime = Get-Date
        $StopTime = (get-date).AddMinutes($MaxMins)
        "Stop time is: $StopTime"

        # Embedded cleanup function.
        function clean-up {
          "THE END"
        }

    } 

    process 
    {  
        $currTime = Get-Date
        if( $currTime -lt $StopTime ){
            "Processing $Foo"            
        }
        else {
            # Call the cleanup function just before stopping the pipeline.
            clean-up
            continue;
        }
    }

    end { 
      # Normal termination: call the cleanup function.
      clean-up
    }
}

【讨论】:

    猜你喜欢
    • 2019-06-22
    • 2012-02-03
    • 2015-02-28
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多