PowerShell Start-Service Timeout

2019-07-23 05:17发布

问题:

Problem

I have been working on a timeout feature for the Start-Services feature of my application and have stumbled upon some setbacks in which the timeout doesn't work properly or fails to display properly.

My two constants are set as such:

$timeout = New-TimeSpan -Seconds $SecondsToWait
$elapsedTime = [System.Diagnostics.Stopwatch]::StartNew()

The rest of my code has changed multiple time to try and achieve my goal. I have tried all of the following with little or no success. Each attempt will have a brief description:

In this instance, I attempted to create a new job, put the action inside of a Do While loop and Exit said loop if Elapsed Time = Timeout time or Job State is 'Running'. Unfortunately, this breaks during the while loop.

$j = Start-Job -ScriptBlock { Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue }

Do {
    If ($j.State -eq "Running") { break }
    $j | Receive-Job
} While ($elapsedTime -le $timeout)

I attempted the Do While loop in a different format, but still had issues getting it to work as it hits an infinite loop at the Start-Service line when it runs into a service it cannot start automatically.

Do {
    $counter++
    Start-Sleep 1
    Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue

    # this line is just a custom function that gets the status of the service and checks a number of times based on the 'SecondsToWait' Parameter. 
    Wait-ServiceState -ServiceName $ServiceName -ServiceState "Running" -SecondsToWait 1
} While ($elapsedTime -le $timeout)

This too breaks at the Start-Service Cmdlet for a similar reason as the above instance

Do {
    $counter++
    Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
} While ($elapsedTime -eq $timeout)

I also tried using Write-Progress instead as a more dymanic variant... but that didn't do much in terms of initializing the Start-Services argument.

I have tried reading through several posts as well in hopes of finding alternative ways to do this, but even those variations failed... And as much as I liked the way Write-Progress worked... I couldn't understand how to clear it from the screen (without clearing the entire cmd screen) or how to control where it appears on the cmd window. Anyways, you can find those alternative resourses below:

Powershell timeout service

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/start-job?view=powershell-5.1

Powershell Start Process, Wait with Timeout, Kill and Get Exit Code

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/write-progress?view=powershell-5.1

Question

Does anyone know how to resolve the issues with my code that would help me not only timeout the Start-Process, but to display the elapsed time properly?

Thanks in advance

回答1:

You created a stopwatch called $elapsedTime

$elapsedTime = [System.Diagnostics.Stopwatch]::StartNew()

That is kind of confusing because the name you chose is not what it seems. Therefore, when you want to compare against your timeout, $elapsedTime is not the elapsed time represented as a timespan, as you might think quickly reading variable name, it is your Stopwatch object.

Therefore, your

 While ($elapsedTime -le $timeout)

should in fact be

While ($elapsedTime.Elapsed -le $timeout)