NAVANEM
Service Management[PowerShell]medium5 min read · jun 13, 2026 · 06:29 utc

Restart Windows services on remote servers with email alerts

Restart one or more Windows services on remote servers, ping-checked, with success/failure email alerts. Pipeline-driven, -WhatIf safe, and fixes the en-dash/curly-quote bugs in the original.

by Emanuel De Almeida

A small but genuinely useful piece of plumbing: restart a named service on one or more remote servers, check the box is actually reachable first, and get an email when it is done (or when it breaks). Handy for scheduled "bounce this flaky service at 3am" jobs or quick remote remediation.

What it does

For each target it pings the server, restarts the named service(s), and emails a per-action report. It takes pipeline input, so you can feed it a list of server/service pairs and let it work the list. Email is optional, omit the mail parameters and it just restarts and logs.

What I rebuilt

The source copy had two silent bugs from a bad paste that stop it dead in PowerShell:

  • if ($intPingError –eq 0) used an en-dash () instead of the operator hyphen, which is a parse error.
  • Several Write-Host lines used curly quotes ("...") instead of straight quotes, another parse error.

Both are fixed here. On top of that:

  • Renamed to approved verbs (Restart-RemoteService, Send-Notification) instead of FuncRestartService / FuncMail.
  • Added `[CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]`, so -WhatIf previews every restart and scheduled runs pass -Confirm:$false.
  • Pipeline input and multiple services per server, replacing the hard-coded call list.
  • Real error handling ($($_.Exception.Message) instead of dumping the whole $Error history), return instead of break to exit cleanly, Test-Connection instead of hand-rolled System.Net.NetworkInformation.Ping, and the mail objects are disposed.

Notes

Needs rights to control services on the remote host (Get-Service / Restart-Service use RPC/DCOM on PowerShell 5.1) and an SMTP server for the optional alerts. Run with -WhatIf first. Adapted from a script on SQLServerCentral; test before production.

The script

powershell-restart-remote-windows-services.ps1
#Requires -Version 5.1

<#
.SYNOPSIS
    Restarts one or more Windows services on one or more remote servers, pinging
    first and emailing the outcome (or any failure). Honours -WhatIf / -Confirm.
.DESCRIPTION
    For each target the script tests connectivity, restarts the named service(s),
    and sends an email report on success or failure. It accepts pipeline input,
    so you can feed it a list of server/service pairs and let it work through
    them. Email is optional: omit the mail parameters to just restart and log.
.PARAMETER ComputerName
    The remote server. Pipeline-bindable (alias: Server).
.PARAMETER ServiceName
    One or more service names to restart on that server (alias: Service).
.PARAMETER To / From / SmtpServer
    Supply all three to receive an email report per action.
.EXAMPLE
    Restart-RemoteService -ComputerName SQL01 -ServiceName MSSQLSERVER -To it@example.com -From noreply@example.com -SmtpServer smtp.example.local
.EXAMPLE
    # Dry run a batch from the pipeline
    @(
        [pscustomobject]@{ ComputerName = 'SQL01'; ServiceName = 'MSSQLSERVER' }
        [pscustomobject]@{ ComputerName = 'WEB01'; ServiceName = @('W3SVC', 'WAS') }
    ) | Restart-RemoteService -To it@example.com -From noreply@example.com -SmtpServer smtp.example.local -WhatIf
.NOTES
    Author : Emanuel De Almeida - https://www.navanem.com
    Adapted from a script on SQLServerCentral (script 87230). Test before production.
#>

function Send-Notification {
    param(
        [string[]] $To,
        [string]   $From,
        [string]   $Subject,
        [string]   $Body,
        [string]   $SmtpServer
    )
    if (-not ($To -and $From -and $SmtpServer)) { return }   # email is optional
    $msg = New-Object Net.Mail.MailMessage
    $smtp = New-Object Net.Mail.SmtpClient($SmtpServer)
    try {
        $msg.From = $From
        foreach ($addr in $To) { $msg.To.Add($addr) }
        $msg.Subject = $Subject
        $msg.IsBodyHtml = $true
        $msg.Body = $Body
        $smtp.Send($msg)
    }
    catch {
        Write-Warning "Could not send notification: $($_.Exception.Message)"
    }
    finally {
        $msg.Dispose()
        $smtp.Dispose()
    }
}

function Restart-RemoteService {
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    param(
        [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
        [Alias('Server')]
        [string] $ComputerName,

        [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
        [Alias('Service')]
        [string[]] $ServiceName,

        [string[]] $To,
        [string]   $From,
        [string]   $SmtpServer
    )

    process {
        $mail = @{ To = $To; From = $From; SmtpServer = $SmtpServer }

        if (-not (Test-Connection -ComputerName $ComputerName -Count 2 -Quiet)) {
            Write-Warning "$ComputerName is not responding to ping; skipping."
            Send-Notification @mail -Subject "Server: $ComputerName - Status" -Body "$ComputerName is not responding to ping. Please investigate."
            return
        }

        foreach ($svc in $ServiceName) {
            if (-not $PSCmdlet.ShouldProcess("$ComputerName\$svc", 'Restart service')) { continue }
            try {
                $service = Get-Service -ComputerName $ComputerName -Name $svc -ErrorAction Stop
                Restart-Service -InputObject $service -Force -ErrorAction Stop
                Write-Output "Restarted $ComputerName\$svc."
                Send-Notification @mail -Subject "Server: $ComputerName - Restart" -Body "$ComputerName\$svc has been restarted."
            }
            catch {
                Write-Error "Failed to restart $ComputerName\$svc : $($_.Exception.Message)"
                Send-Notification @mail -Subject "Server: $ComputerName - Error" -Body "$ComputerName\$svc restart failed. Details: $($_.Exception.Message)"
            }
        }
    }
}

# ── Edit and uncomment, or dot-source this file (. .\Restart-RemoteService.ps1) and call the function. ──
# Restart-RemoteService -ComputerName 'Server1' -ServiceName 'ServiceName1' -To 'it@example.com' -From 'noreply@example.com' -SmtpServer 'smtp.example.local'
# Restart-RemoteService -ComputerName 'Server2' -ServiceName 'ServiceName2' -To 'it@example.com' -From 'noreply@example.com' -SmtpServer 'smtp.example.local'

Review before running. Test in a non-production environment first.

#PowerShell#windows#Automation

Related topics