在 powershell 脚本中添加超时部分

Adding Time out section in powershell script

我正在尝试测试 30 秒后超时。

示例代码:

$a = "y"
$b = "n"
$timeout = New-TimeSpan -Seconds 30
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$stopwatch.Start()
$timeout.Seconds
$stopwatch.elapsed.Seconds
do{

    if($a -eq "n"){
        Write-Host "This block will never run"
        break
    }

    if($stopwatch.elapsed.Seconds -lt $timeout.Seconds){
        Write-Host "Testing this block: Time OUT!!"
        break
    }

}while($a -eq $b)

$stopwatch.Stop()

但是 if 块 if($stopwatch.elapsed.Seconds -lt $timeout.Seconds) 为真,即使 $stopwatch.elapsed.Seconds 值为 0 而 $timeout.Seconds 值为 30循环并在几毫秒内完成代码,而不是花费 30 秒来打印超时语句。

谁能给我指点以解决这个问题。

几件事:

  • 您不需要这两行:循环上方的 $timeout.Seconds$stopwatch.elapsed.Seconds
  • 你的 while 条件应该是 while($a -ne $b)
  • 循环内的测试应为if($stopwatch.elapsed.Seconds -ge $timeout.Seconds)

尝试

$a = "y"
$b = "n"
$timeout = New-TimeSpan -Seconds 30
$stopwatch = [System.Diagnostics.Stopwatch]::new()
$stopwatch.Start()
do {
    if($stopwatch.Elapsed.Seconds -ge $timeout.Seconds){
        Write-Host "Testing this block: Time OUT!!"
        break
    }
    # no timeout, so proceed with what needs to be done here
    # . . .
} while($a -ne $b)  # loop forever unless you set $a equal to $b in the loop somewhere

$stopwatch.Stop()

解决了您的方法中附带的 逻辑 问题,并提供了一个 可能 有效但无效的解决方案完全稳健:如果在测试超时条件之前循环 中的 activity 超过 1 分钟 ,测试将不会按预期进行(即使逻辑问题已修复)。

你有两个选择:

  • 使用 .TotalSeconds 而不是 .Seconds,原因如下所述。

  • 更简单地说,利用 [timespan] 实例可直接比较的事实(见下文),您可以使用:

    if ($stopwatch.elapsed -gt $timeout) { # ... 
    

作为 zett42 points out, [timespan] instances are directly comparable, due to implementing the .NET System.IComparable 界面(以及它的通用对应物);例如:

   # -> $true - a timespan representing a 61-second duration 
   #            is greater than one representing a 60-second (1-minute) duration.
   [timespan]::FromSeconds(61) -gt [timespan] '00:01:00'

因此,如上一节所示,您可以直接比较 $stopwatch.elapsed$timeout - 两者都是 [timespan] 个实例。

[timespan]实例的.Seconds属性只有秒分量,可能与 更大的 单位一起使用,例如分钟 (.Minutes) 和小时 (.Hours)

您需要 .TotalSeconds 属性 才能获得 秒数(类似地,还有 .TotalDays.TotalHours.TotalMinutes 属性)。

另请注意 .Seconds 始终是 整数 ([int]),而 .TotalSeconds 可以是 分数值 ([double]).

为了说明区别:

PS> [timespan] '00:01:05' | # 1 minute and 5 seconds 
      Select-Object Seconds, TotalSeconds

Seconds TotalSeconds
------- ------------
      5           65

@sivam 问题是-

  • 如果超过 59 秒,则您没有应用 timespan 命令的正确属性,然后在 60 秒时将其视为 1 分钟。
  • 更新循环内的条件 if($stopwatch.elapsed.Seconds -lt $timeout.Seconds)

尝试

$a = "y"
$b = "n"
$timeout = New-TimeSpan -Minutes 1
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
$stopwatch.Start()
$timeout.Minutes
$stopwatch.elapsed.Minutes
do{
    if($a -eq "n"){
        Write-Host "This block will never run"
        break
    }
    if($stopwatch.elapsed.Minutes -ge $timeout.Minutes){
        Write-Host "Time OUT!!"
        break
    }
}while($a -ne $b)
$stopwatch.Stop()