Powershell:以执行时间限制启动进程,并在运行时从其StdOut中读取

时间:2019-04-08 12:24:41

标签: .net powershell

我正在尝试在PowerShell中启动一个进程(例如ping),设置执行时间限制,如果在截止时间之前没有终止该进程,则终止该进程。

我有一个脚本,可以启动一个进程并在x秒后终止它(简单),一个脚本可以启动一个进程,并在完成后从其StdOut中读取(简单)。

我的代码在x秒后停止进程

$p = Start-Process -FilePath "notepad" -PassThru
Wait-Process -InputObject $p -Timeout 3
Stop-Process -InputObject $p

我的代码来启动进程并从其StdOut中读取

$pinfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{
        FileName = "ping.exe"
        Arguments = "-t 127.0.0.1"
        RedirectStandardOutput = $true
        UseShellExecute =$false
    }
    $p = New-Object System.Diagnostics.Process
    $p.StartInfo = $pinfo
    $outevent = Register-ObjectEvent -Action {Write-Host $Event.SourceEventArgs.Data} -InputObject $p -EventName OutputDataReceived
    $p.Start()
    $p.BeginOutputReadLine()

但是我无法将这两个功能整合到一个脚本中。通常,StdOut读数会阻塞计时器。我想运行一个.exe x秒钟,然后读取当时生成的任何StdOut。

1 个答案:

答案 0 :(得分:0)

I think you could achieve what you're looking for via background jobs. For example:

$Job = Start-Job -ScriptBlock {
    ping.exe 8.8.8.8
}

$TimeOutSeconds = 5

1..$TimeoutSeconds | ForEach-Object {
    $Job | Receive-Job
    if (($Job | Get-Job).State -eq 'completed') {
        Break
    }
    Else {
        Start-Sleep 1
    }
} -End { Write-Warning 'Timeout reached.' }

$Job | Receive-Job

Stop-Job $Job -PassThru | Remove-Job

Explanation:

  • The Start-Job cmdlet creates a background job that executes the defined script block. The cmdlet returns a PSRemotingJob object that we return to $Job to use to reference the job elsewhere in the script.
  • A ForEach-Object loop is use to iterate 5 times with a 1 second delay on each iteration and each time uses the Receive-Job cmdlet to retrieve any output that the background job has produced.
  • If the job has reached a completed state (e.g the execution has ended) then we break the loop. If this occurs the -End scriptblock of the ForEach-Object is never executed.
  • After the 5th iteration the -End block executes and warns the user that we've reached the timeout.
  • We then retrieve any final output from the job and then stop and remove it.