PowerShell: Integrate a timeout in the While loop [Quick Guide]

2:50 pm February 27, 20179650

I. introduction

meet me in this tutorial to talk PowerShell and timeout in order to optimize your scripts in a While loop. Sometimes, we need to wait for that action ends before beginning another, for example wait for change of status of a service, a process or even the end of execution of a scheduled task.

I will introduce the .NET class “ Stopwatch ” since it allows to respond to this need with its timer timeout. You will quickly understand that this class can also be used for other things, like calculate the time of execution of a script, or even a section of a script… Also interesting for the debug.

Learn more about loops Do-While and Do-Until in PowerShell

II. The Stopwatch class

before timeout, let’s start by learning some commands to simply use the Stopwatch class. For those who want to go further, go to help: Help Stopwatch

the Stopwatch class belongs to the namespace System.Diagnostics , we can therefore create and start a new timer with the following command (with the assignment to a variable that will be useful then) via the method StartNew () .

 $timer = [Diagnostics.Stopwatch]: StartNew () 

now the meter will turn… The seconds… To see what the meter, we’ll display the property “ Elapsed.TotalSeconds ” or “ Elapsed.Seconds ” according to the precision of the format that you want. Here are the commands as well as a screenshot that will allow you to understand the difference between the two properties:

 $timer. Elapsed.TotalSeconds $timer. Elapsed.Seconds 

which gives:

to stop the timer, the Stop() method is used:

 $timer. Stop() 

this can also take a break, because if you call the Start() method then the meter will leave taking where he it was arrested. On the other hand, if you call the Reset() method or if you re-create a timer in the same variable ($timer) it will start from scratch.

 $timer. Start() 

you now have the basics of using the Stopwatch class, finish with this loop for that will allow to see that the timer runs well:

 # start the timer/clock $timer [Diagnostics.Stopwatch] =::StartNew() # loop display timer example for ($i = 1; $i - lt 3000; $i ++) {# seconds with milliseconds Write-Host $timer.} Elapsed.TotalSeconds} # stop the timer $timer. Stop() 

with a While loop that works too, to display the counter until it is less than 5 seconds:

 # start the timer/clock $timer = [Diagnostics.Stopwatch]::StartNew() While($timer.) Elapsed.Seconds - lt 5) {Write-Host $timer. Elapsed.TotalSeconds} # stop the timer $timer. Stop() 

turn now to our timeout…

III. Timeout with the Stopwatch class

Finally, we’ll take the idea of the loop as described above, where the value “5” represents the timeout value. It would suffice to define a variable, for example, named $timeout, to assign a value in seconds that’s a timeout in the While loop. On the other hand, it’s more interesting to pair it with another action, because the purpose of a timeout is to secure the code to avoid looping turns to infinity, in normal times, it is not him who should leave the loop.

For example, a piece of code where we expect that a service will move to the “Stopped” State to continue… If this never happens, the loop is going to infinity which is not acceptable. So, we’ll rely on what we saw previously to add a timeout.

Everything is going to play in the loop While, where we are going to say “ as long as the status of the DHCP service is not on Stopped and the timer is less than the timeout, so this action… “.” Which means that as soon as the service will pass on the Stopped State we leave the loop but if it never happens, it is the fact that the timer exceeds the timeout value that we will exit the loop. The status of and (and) is very important in the context of the use of a timeout so that the loop can continue only if both conditions are true.

Moreover, in the action of the While, I advise to trigger breaks every time (up to you to see to the number of seconds according to what you would expect as action) that will avoid making too many loop unnecessarily.

Here is the script in question that I invite you to run on your machine:

 # Timeout in seconds $timeout = 10 # start the timer/clock $timer [Diagnostics.Stopwatch] =::StartNew() # use the timer to create a timeout on a While While (((Get-Service DHCP).) Status - not "Stopped") - and ($timer. Elapsed.TotalSeconds - lt $timeout)) {Write-Host "[$($timer.Elapsed.Seconds)] waiting for stopping the DHCP Client service..."}
  {Start-Sleep - 3 Seconds} # stop the timer $timer. Stop() 

which gives us:

the fact of integrating a timeout means that the script will continue while an action was not successful, which can lead to other problems in the execution of your script. The idea may be to check in an “if” condition if the timer is greater than the timeout, and if it is to complete the script by displaying an error message. The need or not to make this verification depends on the purpose of your script, but I’d rather put you the flea in the ear.

Note : The example of scheduled tasks or the services is more relevant than making the same example with a process, because there is a “Wait-Process” commandlet which lets wait for the end of a process, and it contains a timeout parameter directly.

To wait for the end of execution of a scheduled task that is, she finds the “Ready” State ( Ready ), you can use the following While condition:

 While ((Get-ScheduledTask-TaskName "MaTache").) State - not "Ready")-and ($timer. Elapsed.TotalSeconds - lt $timeout)) 

I’m done with the explanations on the management of a timeout in PowerShell within a While loop, I encourage you to incorporate this type of operation in your scripts to avoid infinite loops. And then feel free to also use the Stopwatch class for other uses. 🙂