Powershell command timeout

后端 未结 2 1332
情歌与酒
情歌与酒 2021-01-23 18:50

I am trying to execute a function or a scriptblock in powershell and set a timeout for the execution.

Basically I have the following (translated into pseudocode):

<
相关标签:
2条回答
  • 2021-01-23 19:40

    Today, I ran across a similar question, and noticed that there wasn't an actual answer to this question. I created a simple PowerShell class, called TimedScript. This class provides the following functionality:

    • Method: Start() method to kick off the job, when you're ready
    • Method:GetResult() method, to retrieve the output of the script
    • Constructor: A constructor that takes two parameters:
      • ScriptBlock to execute
      • [int] timeout period, in milliseconds

    It currently lacks:

    • Passing in arguments to the PowerShell ScriptBlock
    • Other useful features you think up

    Class: TimedScript

    class TimedScript {
      [System.Timers.Timer] $Timer = [System.Timers.Timer]::new()
      [powershell] $PowerShell
      [runspace] $Runspace = [runspacefactory]::CreateRunspace()
      [System.IAsyncResult] $IAsyncResult
    
      TimedScript([ScriptBlock] $ScriptBlock, [int] $Timeout) {    
        $this.PowerShell = [powershell]::Create()
        $this.PowerShell.AddScript($ScriptBlock)
        $this.PowerShell.Runspace = $this.Runspace
    
        $this.Timer.Interval = $Timeout
    
        Register-ObjectEvent -InputObject $this.Timer -EventName Elapsed -MessageData $this -Action ({
          $Job = $event.MessageData
          $Job.PowerShell.Stop()
          $Job.Runspace.Close()
          $Job.Timer.Enabled = $False
        })
      }
    
      ### Method: Call this when you want to start the job.
      [void] Start() {
        $this.Runspace.Open()
        $this.Timer.Start()
        $this.IAsyncResult = $this.PowerShell.BeginInvoke()
      }
    
      ### Method: Once the job has finished, call this to get the results
      [object[]] GetResult() {
        return $this.PowerShell.EndInvoke($this.IAsyncResult)
      }
    }
    

    Example Usage of TimedScript Class

    # EXAMPLE: The timeout period is set longer than the execution time of the script, so this will succeed
    $Job1 = [TimedScript]::new({ Start-Sleep -Seconds 2 }, 4000)
    
    # EXAMPLE: This script will fail. Even though Get-Process returns quickly, the Start-Sleep call will cause it to be terminated by its Timer.
    $Job2 = [TimedScript]::new({ Get-Process -Name s*; Start-Sleep -Seconds 3 }, 2000)
    
    # EXAMPLE: This job will fail, because the timeout is less than the script execution time.
    $Job3 = [TimedScript]::new({ Start-Sleep -Seconds 3 }, 1000)
    
    $Job1.Start()
    $Job2.Start()
    $Job3.Start()
    

    Code is also hosted on GitHub Gist.

    0 讨论(0)
  • 2021-01-23 19:41

    I think you might want to investigate using Powershell runspaces:

    http://learn-powershell.net/2012/05/13/using-background-runspaces-instead-of-psjobs-for-better-performance/

    0 讨论(0)
提交回复
热议问题