How to stop while($true) that contains start-sleep in powershell

倖福魔咒の 提交于 2019-12-13 02:11:32

问题


My google-fu has failed me. I've got a pretty simple script that just tests ping connectivity from one server to another, and displays a runtime at the top.

I'd like to be able to stop this script at any time with a single keypress ("q" in the script) and have it give some basic stats about how long it ran, and how many times it failed.

I can stop the script with ctrl+c, but that completely exits and doesn't allow me to show any stats. Below is my script. Any help is appreciated!

###############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"
}

回答1:


Here is a simple example of using the [console]::KeyAvailable method. To make it usable, you will have to wake up your loop more often, and only execute ping on every 10th (,or so) wake up. (If that makes sense.)

$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
    }    
}

Note: Unfortunately [console]::KeyAvailable does not work in PowerShelISE host so it is a pain to debug :(




回答2:


This post is similar. There CTRL-C is captured and used to quit the loop/script.

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



来源:https://stackoverflow.com/questions/29545166/how-to-stop-whiletrue-that-contains-start-sleep-in-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!