Chris Rasmussen · Photographer · Infrastructure Guy · Code Dabbler · Traveller

PowerShell – Checking Windows services status

As I said in my previous post, PowerShell – Why won’t my scripts execute?, Microsoft Powershell is becoming the way to script and automate tasks in Windows. If you haven’t used PowerShell before, you should definitely look into it. PowerShell has been around for a while in various forms, since mid-2006 approximately.

Exchange Server 2007 is one of Microsoft’s most popular products and it makes extensive use of PowerShell cmdlets. In fact, there are many tasks you can’t do in Exchange Server 2007 without using cmdlets so if you have Exchange 2007 installation and administration in your future (or your present!) you need to know this stuff. For now though, I’m going to concentrate on the PowerShell basics by writing a script that shows the status of Microsoft IIS running on a selected machine. It’s not designed to show anyone anything about IIS at all but simply to demonstrate PowerShell basics – please see the URL above if you want details on IIS itself.

So, let’s jump straight in. The script you can see below simply checks the status of and displays a very basic report on 4 of the main IIS services – IIS Admin, World Wide Web Publishing Service, FTP and SMTP. Note that your installation of IIS may have some, none or all of these services so you’ll need to modify the list of services to check to suit your needs. The script is heavily commented so you should be able to work out which line to change (hint: it’s line 81!). Enough mucking about – here’s the script.

?View Code POWERSHELL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# Windows Powershell script to show the status of IIS6+ (HTTP only, doesn't include FTP or SSL)
#
# The script has been written using PowerShell functions to make the whole thing shorter
#
# Checks for the IIS Admin, World Wide Web Publishing Service, FTP Publishing Service, NNTP and SMTP services
#
# Chris Rasmussen, March 2008
 
# be tidy - clear the screen
cls
 
# show a welcome message
write-host "IIS6+ Status Summary"
write-host "--------------------"
write-host ""
 
# this function accepts the name of a service (either the display name or short name) and the name of a machine to check
# the services on the specified machine are enumerated to see if the specified service exists
# if the service does exist the status is checked
# if the service does not exist an appropriate error is displayed
function checkService ($serviceName, $machineName) {
 
	# do some very basic error checking
	if (($serviceName -eq $null) -or ($machineName -eq $null))
	{
		write-host "Service or machine name missing.  Please correct and retry."
	}
	else
	{
		# use the .NET abilities of PowerShell to get a list of all services that match the service name we're looking for
		# note that we are checking both the short and display names, i.e. you can check for either
		# e.g. "iisadmin" and "IIS Admin Service" will both work
		$serviceResults = [System.ServiceProcess.ServiceController]::GetServices($machineName) | where{ (($_.name -eq $serviceName) -or ($_.displayname -eq $serviceName))
}
 
		# check to see if the results is an empty object
		# if it is empty the requested service wasn't found
		if ($serviceResults -eq $null)
		{
			# the service wasn't found so set the result to an empty string (it's used later)
			$isServiceFound = ""
		}
		else
		{
			# the service was found so get the service's name
			$isServiceFound = $serviceResults.name
		}
 
		# check to see if any service names were returned
		if ($isServiceFound -eq "")
		{
			# the service wasn't found
			$resultDisplay = "Not found"
		}
		else
		{
			# the requested service was found so get its status
			$serviceStatus = get-service $isServiceFound
			$resultDisplay = $serviceStatus.status
		}
 
		# return the result of the service check
		if ($resultDisplay -eq "Running")
		{
			# it is running so display an appropriate confirmation in normal text colour
			write-host "$serviceName : " -noNewLine
			write-host $resultDisplay
		}
		else
		{
			# the service isn't running to display a warning in red text colour
			write-host "$serviceName : " -noNewLine
			write-host $resultDisplay -foregroundColor('red')
		}
	}
}
 
# this line dynamicaly loads the .NET assemblies into memory so they can be used by this script
$loadAssemblies = [System.Reflection.Assembly]::LoadWithPartialName('system.serviceprocess')
 
# setup the list of services we want to check
# modify this array to suit your needs
$serviceList = "IIS Admin Service", "World Wide Web Publishing Service", "msftpsvc", "smtpsvc", "nntpsvc"
 
# loop through the list of services and check then report on the status of each one
foreach ($serviceEntry in $serviceList)
{
	# try and get the service's status (if it exists)
	checkService $serviceEntry 'localhost'
}

To run the script you’ll need to have PowerShell installed – it can be downloaded from the Microsoft Powershell website and you’ll need to have the execution policy set so that scripts can actually be executed. My previous article, PowerShell – Why won’t my scripts execute?, covers how to do this.

The full script above can be downloaded by clicking here.

Enjoy!

5 Responses to “PowerShell – Checking Windows services status”

  1. Ju says:

    Scuz for my english i’m french but thanks a lot , your script hightly help me for a part of my work which request for all service which begin by “Wm” for enter them into a database with its status .

    $machineName = “w-pau-104230″
    $servicename = “Wm*”
    $eachprocess = [System.ServiceProcess.ServiceController]

    # use the .NET abilities of PowerShell to get a list of all services that match the service name we’re looking for
    # note that we are checking both the short and display names, i.e. you can check for either
    # e.g. “iisadmin” and “IIS Admin Service” will both work
    $serviceResults = [System.ServiceProcess.ServiceController]::GetServices($machineName) | where {$_.name -like $servicename}
    $eachprocess = $serviceResults
    $serviceResults = [System.ServiceProcess.ServiceController]
    foreach ( $serviceResults in $eachprocess)
    {
    # check to see if the results is an empty object
    # if it is empty the requested service wasn’t found
    if ($serviceResults -eq $null)
    {
    # the service wasn’t found so set the result to an empty string (it’s used later)
    $isServiceFound = “”
    }
    else
    {
    # the service was found so get the service’s name
    $isServiceFound = $serviceResults.name
    }

    # check to see if any service names were returned
    if ($isServiceFound -eq “”)
    {
    # the service wasn’t found
    $resultDisplay = “Not found”
    }
    else
    {
    # the requested service was found so get its status
    $serviceStatus = get-service $isServiceFound
    $resultDisplay = $serviceStatus.status
    }

    # return the result of the service check
    if ($resultDisplay -eq “Running”)
    {
    # it is running so display an appropriate confirmation in normal text colour
    write-host “$isServiceFound.name : ” -noNewLine
    write-host $resultDisplay
    }
    else
    {
    # the service isn’t running to display a warning in red text colour
    write-host “$isServiceFound.name : ” -noNewLine
    write-host $resultDisplay -foregroundColor(’red’)
    }
    }

  2. Andrea says:

    Chris,

    I’d like to run something similar to this on multiple servers on multiple services. If all the services are started on the server I’d like the output to be Servername OK instead of listing each service. I’ve been beating my head against the wall to try and figure this out but I just can’t get it. Any thoughts?

    Thanks

    A

    • Chris says:

      Andrea: Sure, that shouldn’t be too hard. Currently the function returns the service name and the status, as you know. You could quite easily modify the function so that instead of returning a string value representing the service name and the status you just return $true if the result is OK or $false if the result is not OK. E.g. here’s the above script but modified to do just that – hope it helps & please post another comment here if you need more help. :)

      # Windows Powershell script to show the status of IIS6+ (HTTP only, doesn’t include FTP or SSL)
      #
      # The script has been written using PowerShell functions to make the whole thing shorter
      #
      # Checks for the IIS Admin, World Wide Web Publishing Service, FTP Publishing Service, NNTP and SMTP services
      #
      # Chris Rasmussen, March 2008

      # be tidy – clear the screen
      cls

      # show a welcome message
      write-host “IIS6+ Status Summary”
      write-host “——————–”
      write-host “”

      # this function accepts the name of a service (either the display name or short name) and the name of a machine to check
      # the services on the specified machine are enumerated to see if the specified service exists
      # if the service does exist the status is checked
      # if the service does not exist an appropriate error is displayed
      function checkService ($serviceName, $machineName)
      {

      # do some very basic error checking
      if (($serviceName -eq $null) -or ($machineName -eq $null))
      {
      write-host “Service or machine name missing. Please correct and retry.”
      }
      else
      {
      # use the .NET abilities of PowerShell to get a list of all services that match the service name we’re looking for
      # note that we are checking both the short and display names, i.e. you can check for either
      # e.g. “iisadmin” and “IIS Admin Service” will both work
      $serviceResults = [System.ServiceProcess.ServiceController]::GetServices($machineName) | where{ (($_.name -eq $serviceName) -or ($_.displayname -eq $serviceName))
      }

      # check to see if the results is an empty object
      # if it is empty the requested service wasn’t found
      if ($serviceResults -eq $null)
      {
      # the service wasn’t found so set the result to an empty string (it’s used later)
      $isServiceFound = “”
      }
      else
      {
      # the service was found so get the service’s name
      $isServiceFound = $serviceResults.name
      }

      # check to see if any service names were returned
      if ($isServiceFound -eq “”)
      {
      # the service wasn’t found
      $resultDisplay = “Not found”
      }
      else
      {
      # the requested service was found so get its status
      $serviceStatus = get-service $isServiceFound
      $resultDisplay = $serviceStatus.status
      }

      # return the result of the service check
      if ($resultDisplay -eq “Running”)
      {
      # it is running so return true
      return $true
      }
      else
      {
      # the service isn’t running so return false
      return $false
      }
      }
      }

      # this line dynamicaly loads the .NET assemblies into memory so they can be used by this script
      $loadAssemblies = [System.Reflection.Assembly]::LoadWithPartialName(‘system.serviceprocess’)

      # setup the list of services we want to check
      # modify this array to suit your needs
      $serviceList = “AppInfo”, “AppMgmt”

      # set the initial result to true
      $checkResults = $true

      # loop through the list of services and check then report on the status of each one
      foreach ($serviceEntry in $serviceList)
      {
      $tempCheck = checkService $serviceEntry ‘localhost’
      # try and get the service’s status (if it exists)
      if ($tempCheck -eq $false)
      {
      $checkResults = $false
      break
      }
      }

      if ($checkResults -eq $true)
      {
      write-host “Server OK”
      }
      else
      {
      write-host “Server NOT OK”
      }

  3. Andrea says:

    Sorry. I must be thick. So I’m trying not to run this as a function because I want to output to html for a daily report for the Exchange team. Here is what I have so far. I have ther servers in an array and the services in an array but I still get server ok for all of the services not just one line that says server ok for the server. Doest that make sense?

    [system.reflection.assembly]::LoadWithPartialName(“system.serviceprocess”) | out-null

    cls

    foreach ($server in ‘wrenxb’, ‘wren6′)
    {
    foreach ($serviceName in ‘MSExchangeIS’,”IMAP4SVc”)
    #”MSExchangeMGMT”,”MSExchangeMTA”,”POP3Svc”,”RESvc”,”MSExchangeSA”)
    {
    #$serviceName
    $serviceResults = [System.ServiceProcess.ServiceController]::GetServices($server) | where{ (($_.Name -eq $serviceName))}
    #$serviceResults
    if ($serviceResults -eq $null)
    {
    # the service wasn’t found so set the result to an empty string (it’s used later)
    $isServiceFound = “”
    }else{
    $isServiceFound = $serviceResults.name # the service was found so get the service’s name
    }

    if ($isServiceFound -eq “”) # check to see if any service names were returned
    {
    $resultDisplay = “Not found”# the service wasn’t found
    }else{
    $serviceStatus = Get-wmiobject -class win32_service -computername $server | Where {$_.Name -eq $isServiceFound}
    $resultDisplay = $serviceStatus.state
    }

    if ($resultDisplay -eq ‘Running’)# return the result of the service check
    {
    write-host $server ” ” -noNewLine
    write-host OK
    }else{
    # the service isn’t running to display a warning in red text colour
    write-host $server ” ” -noNewLine
    write-host “$serviceName : ” -noNewLine
    write-host $resultDisplay -foregroundColor(’red’)
    }
    }
    }

  4. Robby says:

    Chris,

    I am looking for something similar to this but able to run against multiple servers. Any help would be greatly appreciated.

    Robby

    Output Example:
    server1: IMAP4Svc – Stopped
    server1: POP3Svc – Running

    server2: IMAP4Svc – Running
    server2: POP3Svc – Stopped

Leave a Reply

Powered by Wordpress | Designed by Elegant Themes