I have built a small powershell script to check if a service is started. If it is not started, try to start it then wait one minute and check again. Keep repeating this process until the service start successfully. I have found the loop does not behave the way I expected in that I seem to have to re-assign the service variable within the loop in order to get the updated status. Here is my code:
$ServiceName = 'Serenade'
$arrService = Get-Service -Name $ServiceName
if ($arrService.Status -ne 'Running'){
$ServiceStarted = $false}
Else{$ServiceStarted = $true}
while ($ServiceStarted -ne $true){
Start-Service $ServiceName
write-host $arrService.status
write-host 'Service started'
Start-Sleep -seconds 60
$arrService = Get-Service -Name $ServiceName #Why is this line needed?
if ($arrService.Status -eq 'Running'){
$ServiceStarted = $true}
}
If I run the code without the third last line (the one with the comment), I get the following output. I can check in the Windows service manager and the service was clearly started after the first loop. Why is that third last line required?
Given this behavior, is there a better way to write this code?
Thank you
This question is related to
powershell
I think you may have over-complicated your code: If you are just checking to see if a service is running and, if not, run it and then stop re-evaluating, the following should suffice:
$ServiceName = 'Serenade'
$arrService = Get-Service -Name $ServiceName
while ($arrService.Status -ne 'Running')
{
Start-Service $ServiceName
write-host $arrService.status
write-host 'Service starting'
Start-Sleep -seconds 60
$arrService.Refresh()
if ($arrService.Status -eq 'Running')
{
Write-Host 'Service is now Running'
}
}
The below is a compact script that will check if "running" and attempt start service until the service returns as running.
$Service = 'ServiceName'
If ((Get-Service $Service).Status -ne 'Running') {
do {
Start-Service $Service -ErrorAction SilentlyContinue
Start-Sleep 10
} until ((Get-Service $Service).Status -eq 'Running')
} Return "$($Service) has STARTED"
[Array] $servers = "Server1","server2";
$service='YOUR SERVICE'
foreach($server in $servers)
{
$srvc = Get-WmiObject -query "SELECT * FROM win32_service WHERE name LIKE '$service' " -computername $server ;
$res=Write-Output $srvc | Format-Table -AutoSize $server, $fmtMode, $fmtState, $fmtStatus ;
$srvc.startservice()
$res
}
Combining Alaa Akoum and Nick Eagle's solutions allowed me to loop through a series of windows services and stop them if they're running.
# stop the following Windows services in the specified order:
[Array] $Services = 'Service1','Service2','Service3','Service4','Service5';
# loop through each service, if its running, stop it
foreach($ServiceName in $Services)
{
$arrService = Get-Service -Name $ServiceName
write-host $ServiceName
while ($arrService.Status -eq 'Running')
{
Stop-Service $ServiceName
write-host $arrService.status
write-host 'Service stopping'
Start-Sleep -seconds 60
$arrService.Refresh()
if ($arrService.Status -eq 'Stopped')
{
Write-Host 'Service is now Stopped'
}
}
}
The same can be done to start a series of service if they are not running:
# start the following Windows services in the specified order:
[Array] $Services = 'Service1','Service2','Service3','Service4','Service5';
# loop through each service, if its not running, start it
foreach($ServiceName in $Services)
{
$arrService = Get-Service -Name $ServiceName
write-host $ServiceName
while ($arrService.Status -ne 'Running')
{
Start-Service $ServiceName
write-host $arrService.status
write-host 'Service starting'
Start-Sleep -seconds 60
$arrService.Refresh()
if ($arrService.Status -eq 'Running')
{
Write-Host 'Service is now Running'
}
}
}
A potentially simpler solution:
get-service "servicename*" | Where {$_.Status -eq 'Stopped'} | start-service
Given $arrService = Get-Service -Name $ServiceName
, $arrService.Status
is a static property, corresponding to the value at the time of the call. Use $arrService.Refresh()
when needed to renew the properties to current values.
MSDN ~ ServiceController.Refresh()
Refreshes property values by resetting the properties to their current values.
Trying to do things as smooth as possible - I here suggest modifying GuyWhoLikesPowershell's suggestion slightly.
I replaced the if and until with one while - and I check for "Stopped", since I don't want to start if status is "starting" or " Stopping".
$Service = 'ServiceName'
while ((Get-Service $Service).Status -eq 'Stopped')
{
Start-Service $Service -ErrorAction SilentlyContinue
Start-Sleep 10
}
Return "$($Service) has STARTED"
Source: Stackoverflow.com