Getting service status on multiple servers

This topic contains 3 replies, has 3 voices, and was last updated by  Sachin Ghagare 2 years, 2 months ago.

  • Author
  • #27271

    Sachin Ghagare

    Hi All,

    I'm new to PowerShell..

    I want to check periodically for service status on several servers for specific services.
    additionally, all these services not exists on all servers. for example, one server can have one or more services from desired list of services.

    Not so sure what i'm doing wrong in below function but i'm getting unexpected results as
    server2 does not having IISAdmin service on it but result show so...

    can someone please advice what am I missing here? Thanks.

    Function Check-Service ()
    $arrServerStatus = @()
    $arrAllSiteServers = 'Server1', 'Server2'
    $Servicestat= Get-Service -name 'IISAdmin', 'BITS'
    Foreach ($siteServer in $arrAllSiteServers)
    foreach ($service in $Servicestat)
    $srv = New-Object psobject
    Add-Member -InputObject $srv -MemberType NoteProperty -Name SiteSystem -Value $siteServer
    Add-Member -InputObject $srv -MemberType NoteProperty -Name ServiceName -Value $service.Name
    Add-Member -InputObject $srv -MemberType NoteProperty -Name ServiceDisplayName -Value $service.DisplayName
    Add-Member -InputObject $srv -MemberType NoteProperty -Name ServiceStatus -Value $service.Status
    $arrServerStatus += $srv

    Return, $arrServerStatus


    SiteSystem ServiceName ServiceDisplayName ServiceStatus
    ———- ———– —————— ————-
    Server1 BITS Background Intel... Running
    Server1 IISAdmin IIS Admin Service Running
    Server2 BITS Background Intel... Running
    Server2 IISAdmin IIS Admin Service Running

  • #27274

    Rob Simmers

    There are a lot of ways to do things, especially in scripting. For instance, when you search for a service that doesn't exist, Get-Service produces a exception:

    PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-Service -Name ServiceDoesntExist
    Get-Service : Cannot find any service with service name 'ServiceDoesntExist'.
    At line:1 char:1
    + Get-Service -Name ServiceDoesntExist
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (ServiceDoesntExist:String) [Get-Service], ServiceCommandException
        + FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand

    In order to trap an exception, you would do something like this:

    try {
        Get-Service -Name WSearch, IISAdmin -ErrorAction Stop
    catch {

    This would give you the error message that was displayed, which you could parse to get the name of the service and create a custom message.

    Cannot find any service with service name 'IISAdmin'.

    The pro to this is that you are only searching for certain services, but the parsing can be a pain. As you are a beginner, take a look at this approach:

    $ComputerName = "Computer1", "Computer2"
    foreach ($computer in $ComputerName) {
        #Array of services to check
        $servicesToCheck = "WSearch", "IISAdmin"
        #Get all services on the computer
        $services = Get-Service -ComputerName $computer | Select Name, Status
        #Below we are selecting individual objects, so we want to return the results
        #to a variable with all of the results
        $results = foreach ($service in $servicesToCheck) {
            #Query all services to get the service status
            $checkService = $services | Where{ $_.Name -eq $service }
            #if the computer is not null
            if ($checkService) {
                #Select creates a PSObject, so this should be choice 1 when creating objects
                #The last property is a calculated property, since Get-Service does not contain PSComputerName, we
                #create a custom property. An expression is code, so you can even call other commands like 
                #Get-ADComputer -ComputerName $computer | Select -ExpandProperty Description
                #to put the computer's AD description here
                $checkService | Select Name, Status, @{Name="ComputerName";Expression={$computer}}
            else {
                #Since the checkservice is null because the service doesn't exist, you need to generate a custom
                #object. You can do the below, use [pscustomobject] or Add-Member.  You've used the Add-Member, I
                #think you'll see how much cleaner and easier to read the other methods are for create objects
                $props = @{ComputerName=$computer;
                           Status="Not Installed"}
                New-Object -TypeName PSObject -Property $props

    This can easily converted into a function, but it's important to understand the logic and methods used. The con of this approach is that we are getting all of the services and then searching against those results, but most systems will have a couple hundred services and there shouldn't be a huge performance loss unless you are running this against thousands of servers. You'll see references to filter as far left as you can, which means you want to only return what you want in the initial query. Now, let's look at this method using WMI:

    Get-WMIObject -ComputerName "Computer1", "Computer2" -Class Win32_Service -Filter "Name='ZeroConfigService' or Name='IISAdmin'" | Select PSComputerName, Name, State

    WMI will only return the service if it's installed, we are only getting the services we want (Not all services and then trying to see the service exists) and Select is creating the PSObject with all of the information you need. As I said, multiple ways to do things, but hopefully you will understand some of the logic and ways to get service information.

  • #27275

    Robbie Courtney

    There are multiple ways to solve this problem, I took what you had and made it into a function that could accept parameters. You can pass the function the parameters instead of hard coding the computer names and services. If you only have one purpose for it then hard coding the computer names and services would be ok, I just try to make all the functions that I create reusable. I also just return the raw data from services and let the formatting system display the service name, status, and the PSComputername. Invoke-Command adds the PSComputername property which is nice for something like this. You could easily change this to output a PSObject as well if you wanted to.

    I used a simple approach to stop the displays of errors that would show if the computer didn't have that service name by changing the ErrorActionPreference of the cmdlet to SilentlyContinue, this suppresses the output and only s
    hows the status of services that exists. The downside to this approach is it does pollute your $Error variable which is probably not a problem if you are just using powershelgl interactively.

    Im am fairly new to PowerShell as well so my way might not be the best way but its what I came up with. Hope it helps

    function Check-Service
        Invoke-Command -ComputerName $ComputerName -ScriptBlock {Get-Service -Name $args -ErrorAction SilentlyContinue} -ArgumentList $Service

    call the function like this. This requires that PowerShell remoting is turned on.

    Check-Service -Service IISAdmin, BITS -ComputerName Server1, Server2
  • #27276

    Sachin Ghagare

    Thank you very much Rob for detailed and informative explanation...!

    will check your suggestion and let you know results


You must be logged in to reply to this topic.