Working with services is quite common action for any windows administrators. In this post, we will see how to set a list of services to disabled state in remote computers using PowerShell.
Often system administrators get requirement to disable services on list of remote computers. This script will help such admins who are having similar requirement. This script is a simple wrapper based on Get-WMIObject query and Set-Service cmdlets. The advantage with Get-WMIObject is that it can give you the startup mode of a give services. Neither Get-Service nor any other approach(except sc.exe) gives you this information. So I always feel comfortable calling Win32_Service WMI class with Get-WMIObject cmdlets as it returns major set of information. However service objects obtained via Get-WMIObject lagging facility to set a service to disabled. That is when Set-Service cmdlets comes handy. This is one of the less exposed cmdlets – I don’t see many people using this. Rather everyone relying on calling sc.exe from PowerShell.
This script takes two arguments.
- ComputerName : you can pass single or multiple computernames to this parameter as a comma separated. If this parameter is not specified, script works against local computer.
- ServiceName : This is a mandatory parameter where you need to give list of services that you want to stop and disable.
Code
[cmdletbinding()]
param(
[string[]]$ComputerName = $env:ComputerName,
[parameter(Mandatory=$true)]
[string[]]$ServiceName
)
foreach($Computer in $ComputerName)
{
Write-Host "Working on $Computer"
if(!(Test-Connection -ComputerName $Computer -Count 1 -quiet)) {
Write-Warning "$computer : Offline"
Continue
}
foreach($service in $ServiceName)
{
try
{
$ServiceObject = Get-WMIObject -Class Win32_Service -ComputerName $Computer -Filter "Name='$service'" -EA Stop
if(!$ServiceObject)
{
Write-Warning "$Computer : No service found with the name $service"
Continue
}
if($ServiceObject.StartMode -eq "Disabled")
{
Write-Warning "$Computer : Service with the name $service already in disabled state"
Continue
}
Set-Service -ComputerName $Computer -Name $service -EA Stop -StartMode Disabled
Write-Host "$Computer : Successfully disabled the service $service. Trying to stop it"
if($ServiceObject.state -eq "Stopped")
{
Write-Warning "$Computer : $service already in stopped state"
Continue
}
$retval = $ServiceObject.StopService()
if($retval.ReturnValue -ne 0)
{
Write-Warning "$Computer : Failed to stop service. Return value is $($retval.ReturnValue)"
Continue
}
Write-Host "$Computer : Stopped service successfully"
} catch
{
Write-Warning "$computer : Failed to query $service. Details : $_"
Continue
}
}
}
Output
The output of the script is a simple text with the status of disabling & stopping each service.
Hope this helps…
Comments on this entry are closed.
missing remote computer name flag (-computername $Computer) or it will always check local host even when specifying remote host.
Correct line should be:
$ServiceObject = Get-WMIObject -Class Win32_Service -computername $Computer -Filter “Name=’$service'” -EA Stop
Thanks Ajlan. Thats my mistake. I missed it. Updated the code to fix it.
What does the -EA parameter do exactly?
-EA stands for ErrorAction. What PowerShell should do when an error occurs while executing the cmdlet.
Read more about it at https://technet.microsoft.com/en-us/library/hh847884.aspx
This script works great but what if I wanted to add a few things like getting a list of servers and services from a file and also logging the output to a text file or csv or possibly even html?
Thanks for your help!
I do this quite often. Usually I have a text file with each server on its own line, and read them into an array variable. You can do the same with the list of services too if you like. It works like this:
$File = “$PSScriptroot\servers.txt”
$Servers = @()
if (Get-Item $File)
{
(Get-Content $File) | ForEach-Object {$Servers += $_}
}
else
{
write-warning “Server file $File does not exist!”
}
Hi, i can not find the Script nor the code, Could some one please let me know how to download.
Thanks,
Kamal…
Hi Kamal, Thanks for raising the concern. One of the plug-ins that I installed in my blog misbehaved. I have disabled it now. Please check and let me know issue still persists.
Hello.
I have a bunch of comupters named like this companyname-01, companyname-02 but when adding those and running the script it only tries to connect to -01, -02. It dosent seem to see the whole name of the computer. I have tried ” ” befor and after the computername but then i get error.
What to do.
Hi,
It will be helpful in understanding the issue if you post the exact error message.
Hi ,
I wants to disable serveral Remote desktop related running servcies of windows 7 system for more than 300 system of netwok ,
could you please help me on same .
Thanks
Vishal
Vishal,
Copy & paste the code in this post to a file and name as stopdisableservice.ps1. Then run the following command. Remember to update exact name of the service you want to disable.
stopdisableservice.ps1 -ComputerName (get-content c:\comps.txt) -ServiceName
Make sure to include all your computers into c:\comps.txt. First try with 10 computers and then rest.
Great script however, doesn’t stop the service when there are service dependencies. I receive “WARNING: gm1in2 : Failed to stop service. Return value is 3”
Thanks!
Hi,
Use -Force switch with Set-Service cmdlet in the code. That may help you. Let us know how it goes.
Can you modify this to read multiple (say 100) computer names from a text file. I want to stop one service on many computer.
Thank you,
Emily Nicole
Duh, never mind, I see it above. Thanks
Instead of $ServiceObject.Status it should be $ServiceObject.State
Can you provide me the script
Code is available in the post itself.
I made it a little more user-friendly by adding a hint thus:
try {
$ServiceObject = Get-WMIObject -Class Win32_Service -ComputerName $PC -Filter “Name=’$Service'” -EA Stop
if(!$ServiceObject) {
Write-Warning “$PC : No service found with the name $Service. Did you mean one of these?”
(Get-Service “*$Service*” -ComputerName $Computer) | ForEach {$_.Name}
Continue
}
This way, if you only know part of the name, the script will give the correct name(s) to you so you can copy & paste it/them the next time.
Pravin More made a valuable comment (assuming you want this to work — I do)
“Instead of $ServiceObject.Status it should be $ServiceObject.State”
$ServiceObject.Status is going to be “OK”, $ServiceObject.State will be “Running” if the $Service is.
Moral of the story, read all the comments!
Updated to use State property on the service object. Thanks for the feedback.