Prof. Powershell

Get Service Secret

The secret is out. Get-Service has a class called, appropriately enough, GetServices() -- useful if you're managing remote computers.

PowerShell 1.0 is limited when it comes to working with remote computers. Generally WMI and Get-WMIObject are the extent. For example, on the local system you can use Get-Service to manage services. Yet, to do the same thing on a remote computer you normally need to use Get-WMIObject and the Win32_Service class. Would you rather use Get-Service? I have a secret that I'll share on how to accomplish this.

If you pipe the Get-Service command to Get-Member, you'll see that the cmdlet is working with System.ServiceProcess.ServiceController objects. Here's the secret: if you look at the MSDN documentation for this class, you'll discover the class has a method for returning service objects that takes a computer name as a parameter. We can invoke this method, GetServices(), directly like this:

PS C:\> $services=[system.serviceprocess.servicecontroller]::GetServices("CHAOS")

If you look at $services the output will be identical to that of Get-Service. You should also be able to manage services, although it might take an extra step:

PS C:\> $services | where {$_.name -match "spooler"} | stop-service

This should stop the Spooler service on CHAOS. Now remember that $services is a static variable, so if you look at it the Spooler service will show as running. You need to recreate the variable to get the new status. Or simply restart the service:

PS C:\> $services | where {$_.name -match "spooler"} | start-service

If you nee a more dynamic approach, a script block should do the trick:

$svc={Param ([string]$computer=$env:computername)
[system.serviceprocess.servicecontroller]::GetServices($computer)
}

The script block takes a computername as a parameter. I've set the default to the local computer name. Invoke the script block like this:

PS C:\> &$svc "Chaos"

This is still going to return all services so let's make one minor revision to the script block:

$svc={Param ([string]$computer=$env:computername,
  [string]$name="*")
  [system.serviceprocess.servicecontroller]::GetServices($computer) |
  where {$_.name -like $name}
}

Now I can only return specific services by name, although you will need to use both parameters.

PS C:\> &$svc -comp "Chaos" -name "spooler" | start-service

You'll be happy to know the Get-Service in PowerShell 2.0 has a -Computername parameter so you won't have to jump through these hoops.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular