Controlled restart of multiple services

Last time we discussed how to handle Windows services with Microsft Powershell. This time we get a little deeper by restarting multiple services at once with an additional check if they all restart successful.

The challenge

Let’s take a real example where one software installs three services. I often use GFI Faxmaker. It can works as a fax server behind a telephone system and is usually connected through SIP or H323. To send outbound faxes it has to receive the fax from the client as SMTP mail. Therefore the Microsoft SMTP Server service is also needed. Let’s guess we want to restart all relevant services. So we have to restart three services that come with GFI Faxmaker and the Microsft SMTP Service.
Just restarting a service is not a big deal but don’t we want to check wether all services run after the restart? Wouldn’t it be bad if we restart four services but only two of them come up again? So we will check the state of the service and if they don’t start again successfully we want to send an email to have a chance to act.

The implementation

First we have to get the services we want to restart. We already had the ‘Get-Service’ commandlet. As you can see the relevant services of GFI Faxmaker have ‘Faxmaker’ in their names or ‘GFI Faxmaker’ in their display names.

Get-Service
Get-Service Fax
PS C:\Windows\system32> Get-Service | Where-Object DisplayName -Like 'GFI*'

Status   Name               DisplayName
------   ----               -----------
Running  FAXmaker Fax Se... GFI FaxMaker Fax Server
Running  FAXmaker MTA Se... GFI FaxMaker Message Transfer Agent
Running  GFI FaxMaker WSAPI GFI FaxMaker WSAPI
We also have to get the SMTP service:
Get-Service SMTP

 

PS C:\Windows\system32> Get-Service | Where-Object Name -eq 'SMTPSVC'

Status   Name               DisplayName                           
------   ----               -----------                           
Running  SMTPSVC            Simple Mail Transfer Protocol (SMTP)
We now have to filter the Get-Service commandlet to get the four services we need and write those into a variable:
$services = Get-Service | Where-Object {$_.Name -like '*Faxmaker*' -or $_.Name -eq 'SMTPSVC'}
To restart those four services we just have to execute the Restart-Service commandlet once for each service within a ‘foreach’ loop:
foreach ($service in $services)
{
    Restart-Service $service
}

The ‘Restart-Service’ commandlet usually waits until a service is restarted. As soon as it finishes it’s work the next commands of a script will be handled. So we should assume that all services are restarted. Nevertheless there are various resons why something didn’t work as expected. The service start can run into a timeout or the service crashes for any reason. To prove that everything is fine we want to check the service status of each of our four services.

We still have all services in a single variable and have to check that the status of all services is ‘Running’. The easiest way is to check the number of services we have

PS C:\Windows\system32> $services.Count
4

against the services that are in the status ‘Running’

PS C:\Windows\system32> $runningsvc = Get-Service $services.Name | Where-Object Status -eq 'Running'
$runningsvc.count
4

Not to mention that we only have to check whether those two values must be equal to be sure that all the needed services are running.

$services = Get-Service | Where-Object {$_.Name -like '*Faxmaker*' -or $_.Name -eq 'SMTPSVC'}
$runningsvc = Get-Service $services.Name | Where-Object Status -eq 'Running'
if ($services.Count -ne $runningsvc.Count)
{
    Write-Host Not equal
}
else
{
    Write-Host Equal
}

Let’s assume we want to check three times if all is fine to be sure we don’t produce an error message as long as a service needs a little more time to restart. So we have to run this test three times in a loop. As long as there is a difference between the number of running services we wait 30 more seconds (Start-Sleep 30).

$services = Get-Service | Where-Object {$_.Name -like '*Faxmaker*' -or $_.Name -eq 'SMTPSVC'}
$runningsvc = Get-Service $services.Name | Where-Object Status -eq 'Running'

$i = 1
while ($i -le 3)
{
    if ($services.Count -ne $runningsvc.Count)
    {
        Start-Sleep 30
    }
    $i++
}

If there is still a difference we generate an error message and send it as an email:

if ($services.Count -ne $runningsvc.Count)
{
    Send-MailMessage -to "admin@example.com" -from "error@example" -SmtpServer 192.168.100.7 -Subject "Error restarting Services" -Body ($services |Format-Table -AutoSize| Out-String) -encoding ([System.Text.Encoding]::UTF8)
}

 

Conclusion

Usually it should be normal, that a Windows service should run all day long and should just work. Nevertheless there are situations where it is not the case. Restarting services on a daily base is just a workaround but if you need that workaround you can use this post as a base for your individual situation. There is software available without an integrated backup option but with a documented way how to back it up manually. Most times you have to stop the service or services, copy some files and start the services again. You can automate those steps within a Powershell script but you should ensure that after creating the backup all services will run again.

I didn’t describe all steps in detail like the mail option. If you have questions or things aren’t clear enough then pleas feel free to ask your questions within the comments.

Recommendation

While working with Microsoft Powershell it is useful to have a reference about the various commandlets with you. Powershell Reference Pro is a handy app for iOS devices containing information about all commandlets you can think of. Besides the usual Windows commandlets you will find information about Exchange, SharePoint, Skype as well as third party commandlets like this for VMWare Power CLI, Amazon Web Services (AWS), Citrix and others.

‎PowerShell Reference (Pro)
‎PowerShell Reference (Pro)

 

1 thought on “Controlled restart of multiple services

  1. Pingback: Creating Backups of Estos ProCall and MetaDirectory - Blog: Florian Wilke

Leave a Reply

Your email address will not be published.