【问题标题】:How to stop while($true) that contains start-sleep in powershell如何在powershell中停止包含start-sleep的while($ true)
【发布时间】:2015-04-10 08:33:23
【问题描述】:

我的 google-fu 让我失望了。我有一个非常简单的脚本,它只测试从一台服务器到另一台服务器的 ping 连接,并在顶部显示一个运行时。

我希望能够通过一个按键(脚本中的“q”)随时停止此脚本,并让它提供一些关于它运行了多长时间以及失败次数的基本统计信息。

我可以用 ctrl+c 停止脚本,但它会完全退出并且不允许我显示任何统计信息。下面是我的脚本。任何帮助表示赞赏!

###############SETTINGS##########################

#Server to Ping:
$RemoteMachine = "ServerNameorIP"

#Seconds between each ping:
$PingInterval = 5

#File to log results:
$outFile = "C:\PingLog\"+$today+".PingLog.txt"

##################################################


$today = Get-Date -Format "yyyy-MM-dd"

#start a stopwatch for the progress bar
$elapsedTime = [system.diagnostics.stopwatch]::StartNew()

while ($true)
    {
   #Stick a progress bar at the top that shows elapsed time and how often we're pinging:
   write-progress -activity "Now testing ping connectivity to $RemoteMachine every $PingInterval seconds.  Press q to quit." -status "$([string]::Format("Time Elapsed: {0:d2}:{1:d2}:{2:d2}", $elapsedTime.Elapsed.hours, $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds))"

   $pingFails = 0

    #If the ping test fails, say something, and write it out to a log
    if(!(Test-Connection -ComputerName bb-ts-db -Quiet))
        {
        $pingFails++
        $dropTime = Get-Date -Format "MM/dd/yyyy - HH:mm:ss"
        Add-Content -Path $outfile -value ("Connection Lost at:  $dropTime")
        Echo "Connection Lost at $dropTime"
        }


    #Exit the loop if a key is pressed:
    if ($Host.UI.RawUI.KeyAvailable -and ("q" -eq $Host.UI.RawUI.ReadKey("IncludeKeyUp,NoEcho").Character)) 
    {
        Write-Host "Exiting now, don't try to stop me...." -Background DarkRed
        break;
    }

    #Wait the preset amount of time between each ping loop
    Start-Sleep $pingInterval
}


$elapsedTime.stop()

#Display the stats of this session:
echo "Test runtime:       $elapsedTime.Elapsed"
echo "# of failed pings:  $pingFails"

#If there WERE ping fails, write stats to $outFile
if($pingFails -gt 0)
{
    Add-content -Path $outfile -value "`n `n `n"
    Add-content -Path $outfile -value "Test runtime:       $elapsedTime.Elapsed"
    Add-content -Path $outfile -value "# of failed pings:  $pingFails"
}

【问题讨论】:

  • 您可以将 Pings 作为作业运行,然后执行 Do{<check for key press and quit if detected>}While((Get-Job -State Running)) 循环,尽管这种方式会杀死您的整个进度条。

标签: powershell keypress ping exit


【解决方案1】:

这是一个使用 [console]::KeyAvailable 方法的简单示例。为了使其可用,您必须更频繁地唤醒循环,并且仅在每 10 次(或左右)唤醒时执行 ping。 (如果这是有道理的。)

$continue = $true
while($continue)
{
    if ([console]::KeyAvailable)
    {
        echo "Exit with `"q`"";
        $x = [System.Console]::ReadKey() 

        switch ( $x.key)
        {
            q { $continue = $false }
        }
    } 
    else
    {
        # Your while loop commands go  here......
        Start-Sleep -Milliseconds 500
    }    
}

注意:不幸的是 [console]::KeyAvailable 在 PowerShelISE 主机中不起作用,因此调试起来很痛苦:(

【讨论】:

  • 很好,但我不得不使用Sleep 1; Clear,因为Start-Sleep -Milliseconds 500 向我返回了一个错误
【解决方案2】:

这篇文章很相似。 CTRL-C 被捕获并用于退出循环/脚本。

Is there a way to catch ctrl-c and ask the user to confirm?

【讨论】:

  • 这在您没有 start-sleep 或其他需要时间运行的命令时有效,但是一旦您执行 start sleep,99% 的脚本运行时间都发生在if 语句正在检查按键,这与我上面遇到的问题相同。有没有办法让它随时检查按键?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
  • 2020-03-23
  • 2021-07-10
  • 1970-01-01
相关资源
最近更新 更多