PowerShell- Monitoring Multiple Service on a Group of Servers

I got a request to monitor multiple services and send an email to intended recipients. This post explains how to monitor a multiple services on a group of servers. The function Get-ServiceStatusReport comprises of various cmdLets and function to monitor services on a list of servers.

  • Get-Service
  • HTML Ouptut
  • Email Address validation

The Function Get-ServiceStatusReport contains five parameters

  1. ComputerList – List of Servers
  2. ServiceName – Name of Services separated by comma
  3. SMTPMail – SMTP mail address
  4. FromID – Valid Email ID
  5. ToID – Valid Email ID

Function call -

Get-ServiceStatusReport -ComputerList C:\server.txt -includeService  "MySQL","MpsSvc","W32Time" -To pjayaram@app.com -From pjayaram@ app.com -SMTPMail  app01. app.com

OR

Get-ServiceStatusReport -ComputerList C:\server.txt -includeService  MySQL,MpsSvc,W32Time -To pjayaram@app.com -From pjayaram@ app.com -SMTPMail  app01. app.com

You can download the code :- MonitorMultiple Services

Output:-

MultipleServicesReport

Code:-

Function Get-ServiceStatusReport 
{ 
param( 
[String]$ComputerList,[String[]]$includeService,[String]$To,[String]$From,[string]$SMTPMail 
) 
$script:list = $ComputerList  
$ServiceFileName= "c:\ServiceFileName.htm" 
New-Item -ItemType file $ServiceFilename -Force 
# Function to write the HTML Header to the file 
Function writeHtmlHeader 
{ 
param($fileName) 
$date = ( get-date ).ToString('yyyy/MM/dd') 
Add-Content $fileName "<html>" 
Add-Content $fileName "<head>" 
Add-Content $fileName "<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>" 
Add-Content $fileName '<title>Service Status Report </title>' 
add-content $fileName '<STYLE TYPE="text/css">' 
add-content $fileName  "<!--" 
add-content $fileName  "td {" 
add-content $fileName  "font-family: Tahoma;" 
add-content $fileName  "font-size: 11px;" 
add-content $fileName  "border-top: 1px solid #999999;" 
add-content $fileName  "border-right: 1px solid #999999;" 
add-content $fileName  "border-bottom: 1px solid #999999;" 
add-content $fileName  "border-left: 1px solid #999999;" 
add-content $fileName  "padding-top: 0px;" 
add-content $fileName  "padding-right: 0px;" 
add-content $fileName  "padding-bottom: 0px;" 
add-content $fileName  "padding-left: 0px;" 
add-content $fileName  "}" 
add-content $fileName  "body {" 
add-content $fileName  "margin-left: 5px;" 
add-content $fileName  "margin-top: 5px;" 
add-content $fileName  "margin-right: 0px;" 
add-content $fileName  "margin-bottom: 10px;" 
add-content $fileName  "" 
add-content $fileName  "table {" 
add-content $fileName  "border: thin solid #000000;" 
add-content $fileName  "}" 
add-content $fileName  "-->" 
add-content $fileName  "</style>" 
Add-Content $fileName "</head>" 
Add-Content $fileName "<body>" 

add-content $fileName  "<table width='100%'>" 
add-content $fileName  "<tr bgcolor='#CCCCCC'>" 
add-content $fileName  "<td colspan='4' height='25' align='center'>" 
add-content $fileName  "<font face='tahoma' color='#003399' size='4'><strong>Service Stauts Report - $date</strong></font>" 
add-content $fileName  "</td>" 
add-content $fileName  "</tr>" 
add-content $fileName  "</table>" 

} 

# Function to write the HTML Header to the file 
Function writeTableHeader 
{ 
param($fileName) 

Add-Content $fileName "<tr bgcolor=#CCCCCC>" 
Add-Content $fileName "<td width='10%' align='center'>ServerName</td>" 
Add-Content $fileName "<td width='50%' align='center'>Service Name</td>" 
Add-Content $fileName "<td width='10%' align='center'>status</td>" 
Add-Content $fileName "</tr>" 
} 

Function writeHtmlFooter 
{ 
param($fileName) 

Add-Content $fileName "</body>" 
Add-Content $fileName "</html>" 
} 

Function writeDiskInfo 
{ 
param($filename,$Servername,$name,$Status) 
if( $status -eq "Stopped") 
{ 
 Add-Content $fileName "<tr>" 
 Add-Content $fileName "<td bgcolor='#FF0000' align=left ><b>$servername</td>" 
 Add-Content $fileName "<td bgcolor='#FF0000' align=left ><b>$name</td>" 
 Add-Content $fileName "<td bgcolor='#FF0000' align=left ><b>$Status</td>" 
 Add-Content $fileName "</tr>" 
} 
else 
{ 
Add-Content $fileName "<tr>" 
 Add-Content $fileName "<td >$servername</td>" 
 Add-Content $fileName "<td >$name</td>" 
 Add-Content $fileName "<td >$Status</td>" 
Add-Content $fileName "</tr>" 
} 

} 

writeHtmlHeader $ServiceFileName 
 Add-Content $ServiceFileName "<table width='100%'><tbody>" 
 Add-Content $ServiceFileName "<tr bgcolor='#CCCCCC'>" 
 Add-Content $ServiceFileName "<td width='100%' align='center' colSpan=3><font face='tahoma' color='#003399' size='2'><strong> Service Details</strong></font></td>" 
 Add-Content $ServiceFileName "</tr>" 

 writeTableHeader $ServiceFileName 

#Change value of the following parameter as needed 

$InlcudeArray=@() 

#List of programs to exclude 
#$InlcudeArray = $inlcudeService 

Foreach($ServerName in (Get-Content $script:list)) 
{ 
$service = Get-Service -ComputerName $servername 
if ($Service -ne $NULL) 
{ 
foreach ($item in $service) 
 { 
 #$item.DisplayName 
 Foreach($include in $includeService)  
     {                        
 write-host $inlcude                                     
 if(($item.serviceName).Contains($include) -eq $TRUE) 
    { 
    Write-Host  $item.MachineName $item.name $item.Status  
    writeDiskInfo $ServiceFileName $item.MachineName $item.name $item.Status  
    } 
    } 
 } 
} 
} 

Add-Content $ServiceFileName "</table>"  

writeHtmlFooter $ServiceFileName 

function Validate-IsEmail ([string]$Email) 
{ 

                return $Email -match "^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$" 
} 

Function sendEmail   
{  
param($from,$to,$subject,$smtphost,$htmlFileName)   
[string]$receipients="$to" 
$body = Get-Content $htmlFileName  
$body = New-Object System.Net.Mail.MailMessage $from, $receipients, $subject, $body  
$body.isBodyhtml = $true 
$smtpServer = $MailServer 
$smtp = new-object Net.Mail.SmtpClient($smtphost) 
$validfrom= Validate-IsEmail $from 
if($validfrom -eq $TRUE) 
{ 
$validTo= Validate-IsEmail $to 
if($validTo -eq $TRUE) 
{ 
$smtp.Send($body) 
write-output "Email Sent!!" 

} 
} 
else 
{ 
write-output "Invalid entries, Try again!!" 
} 
} 

$date = ( get-date ).ToString('yyyy/MM/dd') 

sendEmail -from $From -to $to -subject "Service Status - $Date" -smtphost $SMTPMail -htmlfilename $ServiceFilename 

}
About these ads

About Prashanth Jayaram

I’m a Database technologist having 8+ years of rich, hands-on experience on Database technologies. I am Microsoft Certified Professional and backed with a Degree in Master of Computer Application. My expertise lies in T-SQL programming, Replication and PowerShell. hobbies are playing sports and drawing.
This entry was posted in PowerShell. Bookmark the permalink.

31 Responses to PowerShell- Monitoring Multiple Service on a Group of Servers

  1. Sudhakar says:

    Hi Prashanth , When i am executing this script with modified parameters getting error “Get-Service : A parameter cannot be found that matches parameter name ‘ComputerList’.
    At line:98 char:37
    + $service = Get-Service -ComputerList <<<< $servername| where { $_.displayname -like "*$ServiceName*"}|select Machine
    Name,Name,status
    Exception calling "Send" with "1" argument(s): "The SMTP server requires a secure connection or the client was not auth
    enticated. The server response was: 5.7.0 Must issue a STARTTLS command first. tu3sm50318392pab.1 – gsmtp"
    At line:129 char:11
    + $smtp.Send( <<<< $body)"

    • Hi Sudhakar,

      Can you tell me how you are executing the code?

      Follow these steps

      Download and Create the function using PowerShell-ISE and call the function with the required parameters.

      ps:\>Get-ServiceStatusReport -ComputerList C:\computer.txt -includeService SQL -To pjayaram@appvion.com -From pjayaram@appvion.com -SMTPMail abcd .apple.com

      In your case, it looks like there is some problem with SMTP server. Its not able to authenticate.

      But you can see an output in the following folder c:\ServiceFileName.htm

      -Prashanth

      • Sudhakar says:

        Hi Prashanth,

        Thank you for your prompt responce.

        When i am trying to execute the function with parameters. It is giving error ” A parameter cannot be found that matches parameter name ‘ComputerName’.” I have checked the file c:\ServiceFileName.htm but when i checked the file it is having “Service Stauts Report – 2014-01-23 Service Details ServerName Service Name status”. I cannot see the data in this report. I believe it is not able to resolve the computerName.

      • have you created a file c:\computer.txt and added servername like

        c:\computer.txt

        abc
        def

        -Prashanth

      • Sudhakar says:

        Hi Prashanth ,

        Just to share more details..I am using power shell 2 and gmail as a SMTP server . I want to confirm if the script is compatible to powershell 2..

      • Yes script is compatible with PowerShell 2.0. Can you tell me the steps? I doubt it will work with Gmail SMTP configuration.

        -Prashanth

  2. Lady says:

    How am I going to send the report to multiple recipients?

    • Hello,

      Replace the sendEmail function code by below content
      **********************************************************
      Function sendEmail
      {
      param($from,$to,$subject,$smtphost,$htmlFileName)
      [string]$receipients=”$to”
      $body = Get-Content $htmlFileName
      $body = New-Object System.Net.Mail.MailMessage $from, $receipients, $subject, $body
      $body.isBodyhtml = $true
      $smtpServer = $MailServer
      $smtp = new-object Net.Mail.SmtpClient($smtphost)
      $smtp.Send($body)
      }

      separate the toID field with comma.

      ps:\>Get-ServiceStatusReport -ComputerList C:\server.txt -includeService MySQL,MpsSvc,W32Time -To “pjayaram@avion.com,test@avion.com” -From pjayaram@avion.com -SMTPMail abc.mail.com

      –Prashanth

    • Sudhakar Paradesi says:

      Hi Prashanth,

      I have tried with the modified script..but no luck.

      Enclosed is the screenshots for your reference.

      On Tue, Jan 28, 2014 at 8:09 PM, Prashanth Jayaram wrote:

      > Lady commented: “How am I going to send the report to multiple > recipients?”

      • code :- Run the below code in Powershell-ISE, the function call is given below

        Function Get-ServiceStatusReport
        {
        param(
        [String]$ComputerList,[String[]]$includeService,[String]$To,[String]$From,[string]$SMTPMail
        )
        $script:list = $ComputerList
        $ServiceFileName= “c:\ServiceFileName.htm”
        New-Item -ItemType file $ServiceFilename -Force
        # Function to write the HTML Header to the file
        Function writeHtmlHeader
        {
        param($fileName)
        $date = ( get-date ).ToString(‘yyyy/MM/dd’)
        Add-Content $fileName “”
        Add-Content $fileName “”
        Add-Content $fileName “”
        Add-Content $fileName ‘Service Status Report ‘
        add-content $fileName ”
        add-content $fileName “”
        add-content $fileName “”
        Add-Content $fileName “”
        Add-Content $fileName “”

        add-content $fileName “”
        add-content $fileName “”
        add-content $fileName “”
        add-content $fileName “Service Stauts Report – $date
        add-content $fileName “”
        add-content $fileName “”
        add-content $fileName “”

        }

        # Function to write the HTML Header to the file
        Function writeTableHeader
        {
        param($fileName)

        Add-Content $fileName “”
        Add-Content $fileName “ServerName”
        Add-Content $fileName “Service Name”
        Add-Content $fileName “status”
        Add-Content $fileName “”
        }

        Function writeHtmlFooter
        {
        param($fileName)

        Add-Content $fileName “”
        Add-Content $fileName “”
        }

        Function writeDiskInfo
        {
        param($filename,$Servername,$name,$Status)
        if( $status -eq “Stopped”)
        {
        Add-Content $fileName “”
        Add-Content $fileName “$servername”
        Add-Content $fileName “
        $name”
        Add-Content $fileName “
        $Status”
        Add-Content $fileName “”
        }
        else
        {
        Add-Content $fileName “”
        Add-Content $fileName “$servername”
        Add-Content $fileName “$name”
        Add-Content $fileName “$Status”
        Add-Content $fileName “”
        }

        }

        writeHtmlHeader $ServiceFileName
        Add-Content $ServiceFileName “”
        Add-Content $ServiceFileName “”
        Add-Content $ServiceFileName “ Service Details
        Add-Content $ServiceFileName “”

        writeTableHeader $ServiceFileName

        #Change value of the following parameter as needed

        $InlcudeArray=@()

        #List of programs to exclude
        #$InlcudeArray = $inlcudeService

        Foreach($ServerName in (Get-Content $script:list))
        {
        $service = Get-Service -ComputerName $servername
        if ($Service -ne $NULL)
        {
        foreach ($item in $service)
        {
        #$item.DisplayName
        Foreach($include in $includeService)
        {
        write-host $inlcude
        if(($item.serviceName).Contains($include) -eq $TRUE)
        {
        Write-Host $item.MachineName $item.name $item.Status
        writeDiskInfo $ServiceFileName $item.MachineName $item.name $item.Status
        }
        }
        }
        }
        }

        Add-Content $ServiceFileName “”

        writeHtmlFooter $ServiceFileName

        Function sendEmail
        {
        param($from,$to,$subject,$smtphost,$htmlFileName)
        [string]$receipients=”$to”
        $body = Get-Content $htmlFileName
        $body = New-Object System.Net.Mail.MailMessage $from, $receipients, $subject, $body
        $body.isBodyhtml = $true
        $smtpServer = $MailServer
        $smtp = new-object Net.Mail.SmtpClient($smtphost)
        $smtp.Send($body)
        }

        $date = ( get-date ).ToString(‘yyyy/MM/dd’)

        sendEmail -from $From -to $to -subject “Service Status – $Date” -smtphost $SMTPMail -htmlfilename $ServiceFilename

        }

        Get-ServiceStatusReport -ComputerList C:\server.txt -includeService MySQL,MpsSvc,W32Time -To “pjayaram@avion.com,test@avion.com” -From pjayaram@avion.com -SMTPMail abc.mail.com

  3. Sudhakar says:

    The Steps follow:
    The computer list is maintained in the file computer.txt(C:\computer.txt) as per mentioned in the blog.
    The script was copied and executed with the help of powrshell-Ise. The arguments were modified such as mail id and smtp address and executed.
    The script is creating the file in the C drive with proper data,but it fails to send the mail with the error like “Exception calling “Send” with “1” argument(s): “The SMTP server requires a secure connection or the client was not authenticated.”

  4. John Bryant says:

    Nice script, going to try and get it to where it only emails if there is a service stopped

    JB

  5. Parveen says:

    Hi All,

    I changed the sendmail function a bit and make it Gmail SMTP specific and it works for me, so here is what I changed.

    Function sendEmail
    {
    param($subject,$htmlFileName)
    $smtp = New-Object Net.Mail.SmtpClient(‘smtp.gmail.com’, 587)
    $smtp.EnableSsl = $true
    $smtp.Credentials = New-Object System.Net.NetworkCredential(‘GmailAccountName@Gmail.com’, ‘PasswordofTheGmailAccount’)
    $body = New-Object System.Net.Mail.MailMessage
    $body.isBodyhtml = $true
    $body.Subject = $subject
    $body.From = ‘GmailAccountName@Gmail.com’
    $body.To.Add(‘GmailAccountName@Gmail.com’)
    $body.Body = Get-Content $htmlFileName
    $smtp.Send($body)
    }

    If you want to use this for Gmail SMTP replace the sendEmail function code by above content.

    Thanks.

  6. dheeraj says:

    hi Prashanth can u plz explain indetail how to execute the above script.What changes we have to made in script.
    I am trying to run through powershell,file extension with .ps1. i am uable to get mails

    • Hi Dheeraj,
      Are you able to create the Function?. Open Powershell-ISE and copy the code and execute it. Once done you just need to call the function

      Get-ServiceStatusReport -ComputerList C:\server.txt
      -includeService “MySQL”,”MpsSvc”,”W32Time”
      -To pjayaram@app.com
      -From pjayaram@ app.com
      -SMTPMail app01. app.com

      Let me know if you face any difficulty.

  7. Louis says:

    Hi Prashanth, what a great script. I am wondering if it is possible to specify a different set of credentials?

    Any I ideas?

    Thanks

    • Hi Louis,

      Get-service cmdlets donot accept credential parameter.

      In your case, you can try using

      $User = “”
      $Pass = ConvertTo-SecureString “” -AsPlainText -Force
      $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User,$Pass

      Get-WMIObject Win32_Service -Computername -Credential $credential

      –Prashanth

  8. Sudhakar Paradesi says:

    Hi Prashanth,

    I have tested the script with the help of the console and it is working fine. I just to check how can this script will be scheduled with the help of the SQL Server job. I have checked the console but i cannot see this function saved. Pleas do the needful.

  9. Sudhakar Paradesi says:

    Hi Prashanth,

    Just to know as i have execute the script it is showing all the sql server services, but my requirement is to monitor the agent,ssis,sqlserver,sql server agent. Please help me for this..

  10. Sudhakar Paradesi says:

    Hi Prashanth,

    As we need to monitor the servers across different domains. Can it be possible to monitor by passing the credentials in this script ?

    • Hi Sudhakar,

      Yes, its possible.

      You need to pass the credential information. for example

      I’ve used Get-service cmdlet which will not accept credential parameter hence you need to use win32_Service object.

      I’ve shown the below example. You need to modify the code as per your requirement

      $User = “test”
      $Pass = ConvertTo-SecureString “test#%)” -AsPlainText -Force
      $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User,$Pass
      $Computers =”
      Get-WMIObject Win32_Service -computer $computers -credential $Credentials

      Let me know in case any issues
      –Prashanth

  11. Sudhakar Paradesi says:

    HI Prashanth,

    I have executed the report and working fine. I need some modifications like for clustered envirnoment it is showing the service down in passive node. Is it possible to show only the active node?

  12. Hari says:

    Hi Prashanth,

    Is it possible to send htm file as attachment instead of as body in mail.

    With Thanks and regards,
    Prasad

    • Hi Hari,

      Its very simple. Can you refer the below link

      http://sqlpowershell.wordpress.com/2014/05/21/powershell-os-inventory-and-disk-info-consolidated-excel-file-email/

      You need to replace the below code and pass the filename as its parameter

      Function sendEmail([string]$emailFrom, [string]$emailTo, [string]$subject,[string]$body,[string]$smtpServer,[string]$filePath)
      {
      #initate message
      $email = New-Object System.Net.Mail.MailMessage
      $email.From = $emailFrom
      $email.To.Add($emailTo)
      $email.Subject = $subject
      $email.Body = $body
      # initiate email attachment
      $emailAttach = New-Object System.Net.Mail.Attachment $filePath
      $email.Attachments.Add($emailAttach)
      #initiate sending email
      $smtp = new-object Net.Mail.SmtpClient($smtpServer)
      $smtp.Send($email)
      }

      #Call Function

      $message = @”
      Hi Team,

      The Discovery of Windows Server and Disk Space information for all the listed instances.

      Autogenerated Email!!! Please do not reply.

      Thank you,
      XYZ.com

      “@
      $date=get-date

      sendEmail -emailFrom $fromEmail -emailTo $ToEmail -subject “Windows Server Inventory & Disk Details -$($date)” -body $message -smtpServer $SMTPMail -filePath $filename

      Let me know in case of any difficulties

      –Prashanth

  13. hari says:

    Hi Prashanth,

    We have 3 instances on same cluster. I used cluster virtual name for each instance separately. But in report along with instace 1 is displaying as running, but other 2 instances also displaying as stopped along with instance 1. Same with instance 2 along with 1 and 3 so on. Could you please help us.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s