PowerShell Pipeline

Managing Services, Part 2: Working with Service States

Here's how to easily turn on and off services in PowerShell.

While querying services is nice to do in order to see what is happening with a service, sometimes we need to do something more such as starting the services or modifying the start mode of the service to manual from automatic.

Starting and Stopping a Service
Starting and stopping a service can be done as simply as calling Stop-Service and Start-Service. We can also restart a service with ... you guess it, Restart-Service. 

We can supply the name of the service with the cmdlet to perform the action that we want to have happen.

Stop-Service -Name BITS -Verbose 
[Click on image for larger view.]  Figure 1. Stopping a service using Stop-Service.

Another option is to pass a collection of services from Get-Service over to Stop/Start-Service and it will process each service and perform the stopping or starting of each service. In this case, I am looking for services which start with the letter "s" and then I will pass that to Stop-Service. However, in this case I won't actually be stopping them as I will be using –WhatIf to just simulate the stopping of the services.

Get-Service -Name s* | 
Stop-Service -WhatIf
[Click on image for larger view.]  Figure 2. Simulated stopping of all services that start with "s."

If you are attempting to stop a service that has dependents, it will fail unless you use the –force parameter.

[Click on image for larger view.]  Figure 3. Stopping a servce that has dependents.

Starting a service is just as simple as stopping one.

Start-Service -Name BITS -Verbose
[Click on image for larger view.]  Figure 4. Starting a service up.

If you wanted to see the resulting object from using these cmdlets, you can use the –PassThru parameter to display the object after performing the action.

Using the *-Service cmdlets are not the only approach that I have to starting and stopping the services. I can also take advantage of the available methods under the Win32_Service class objects to perform the same type of actions.

I can use Get-CIMInstance and Invoke-CIMMethod to start and stop these services. In this case, I am looking to start the stopped services which should actually be running. I do this by getting all services that should be running and the pipe the objects into Invoke-CIMMethod cmdlet and using the StartService method.

Get-CimInstance -ClassName Win32_Service  -Filter "StartMode='Auto'  And State='Stopped'" |
Invoke-CimMethod -MethodName StartService  
[Click on image for larger view.]  Figure 5. Starting up stopped services set to Auto.

The return value of 0 means that the attempt to start the service has succeeded and no issues were encountered. This doesn't mean that the service is actually running, just that the attempt to start it was successful. You would need to rerun the code to ensure that all services are actually running.

Remote services can be handled the same way using either of these approaches, but some care needs to happen in order to ensure that this works correctly. You might have noticed that Stop/Start/Restart-Service doesn't have a Computername parameter whereas Get-WMIObject does have a Computername parameter which makes it easier to manipulate the service state. We can get around this by using the –InputObject parameter of each of the *-Service cmdlets.

The trick here is to first get the service (or services) using Get-Service and then you can either pipe that right into your cmdlet of choice or save the objects to a variable and then use the –InputObject parameter to manipulate the services on the remote system.

# Stopping remote services 
Get-Service HTTP -DependentServices -ComputerName Boe-PC |
Stop-Service -Force -Verbose
# Starting remote services 
$Service = Get-Service HTTP -DependentServices -ComputerName Boe-PC
Start-Service -InputObject $Service -Verbose

Pretty simple, right?

Changing the Start Mode of a Service
There may be times when a service is set to Auto and it doesn't start for some reason and the best solution is to change the StartMode to manual so it only starts when a specific program requires it. Other times you have a disabled service which now needs to be set to Auto. Either way, this can be accomplished by using the either the Set-Service cmdlet or taking advantage of some methods that are part of the Win32_Service class object.

We will first start off by working with Set-Service and then move onto Get-WMIObject and even look at Invoke-WMIMethod as the WMI approaches to changing the StartMode of a service.

Much like how we used the Start/Stop-Service, we can use Set-Service to manipulate the StartMode of the service by using the –StartupType parameter and the specifying one of the allowed arguments (Manual, Automatic and Disabled). You may have also seen the use of –StartMode as well in the help file and this is actually an alias for StartupType, so don't be surprised if this gets interchanged sometimes.

Now let's go ahead and change the StartMode of a service.

Set-Service -Name WinRM -StartupType  Disabled -Verbose 
[Click on image for larger view.]  Figure 6. Startmode of WinRM changed to Disabled.

And we can simply change it back to Automatic without much effort at all.

Set-Service -Name WinRM -StartupType  Automatic -Verbose 

Pretty painless and unlike the other cmdlets that I have already discussed, this one does come with a –Computername parameter for working with remote services.

Working WMI means that we have alternate methods for performing the same action on a service. This method that we will use is called ChangeStartMode which we can find by viewing the methods of the object.

$Service = Get-WmiObject -Class Win32_Service -Filter  "Name='WinRM'"
$Service | Get-Member -MemberType Method
[Click on image for larger view.]  Figure 7. Available methods for Win32_Service.

Much like the –StartupType parameter, this method takes a string that represents a StartMode for the service.

$Service.ChangeStartMode('Disabled') 

We can rerun the query again to verify that the StartMode has been set to Disabled. Once that has been done, you can change the mode back to Automatic.

$Service.ChangeStartMode('Automatic') 

Keep in mind that each time that you use this, it does return an object which shows the return value of the command. If it is anything other than a 0, then you will need to look up the code to determine the error and the next course of action for troubleshooting.

I promised the use of Invoke-WMIMethod and here it is!

Invoke-WmiMethod -Path "Win32_Service.Name='WinRM'"  -Name ChangeStartMode  -ArgumentList 'Disabled' 

Note that I had to use the –Path parameter because I am specifying the name of the service in the Win32_Service class.

In summary, we have seen multiple ways to change the StartMode of a service as well as starting and stopping services on both a local and remote system. With this knowledge, you can more easily manage services from the comfort of your local workstation rather than using something like remote desktop to log in and perform these tasks!

About the Author

Boe Prox is a Microsoft MVP in Windows PowerShell and a Senior Windows System Administrator. He has worked in the IT field since 2003, and he supports a variety of different platforms. He is a contributing author in PowerShell Deep Dives with chapters about WSUS and TCP communication. He is a moderator on the Hey, Scripting Guy! forum, and he has been a judge for the Scripting Games. He has presented talks on the topics of WSUS and PowerShell as well as runspaces to PowerShell user groups. He is an Honorary Scripting Guy, and he has submitted a number of posts as a to Microsoft's Hey, Scripting Guy! He also has a number of open source projects available on Codeplex and GitHub. His personal blog is at http://learn-powershell.net.

comments powered by Disqus
Most   Popular