186

I am currently writing a deployment script that installs a number of Windows services.

The services names are versioned, so I want to delete the prior Windows service version as part of the installs of the new service.

How can I best do this in PowerShell?

15 Answers 15

328

You can use WMI or other tools for this since there is no Remove-Service cmdlet until Powershell 6.0 (See Remove-Service doc)

For example:

$service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'"
$service.delete()

Or with the sc.exe tool:

sc.exe delete ServiceName

Finally, if you do have access to PowerShell 6.0:

Remove-Service -Name ServiceName
Sign up to request clarification or add additional context in comments.

6 Comments

You could also port the relevant part of this example to powershell (use the TransactedInstaller class): eggheadcafe.com/articles/20060104.asp However ravikanth's method is probably simpler.
More recent versions of PS have Remove-WmiObject, and beware of silent fails for $service.delete() - have added another answer with formatted examples.
In short, most up to date version is to run Powershell As Administrator and run following: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject
For everyone's information, Straff's answer says "Beware of silent fails for $service.delete()"
Starting in Windows PowerShell 3.0, the cmdlet Get-WmiObject has been superseded by Get-CimInstance. So nowadays you can do this: Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
|
147

There's no harm in using the right tool for the job, I find usign sc.exe (via PowerShell) to be the most reliable method with few dependencies.

Local:

sc.exe delete "MyService"

Remote server:

sc.exe \\server delete "MyService"

6 Comments

The .exe part is very important as sc on its own is an alias for Set-Content.
@tjrobinson Thanks for that, I had omitted the .exe until I saw your comment. Now its working for me.
This is only useful if you have rights to the remote computer. If not (like in most secure environments) this won't work and you'll need something that supports passing in credentials
The server name (\\server) is simply omitted if the service is local.
this is better because it's more easily scriptable with % and $_
|
97

If you just want to check service existence:

if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
    "service exists"
}

Comments

23

I used the "-ErrorAction SilentlyContinue" solution but then later ran into the problem that it leaves an ErrorRecord behind. So here's another solution to just checking if the Service exists using "Get-Service".

# Determines if a Service exists with a name as defined in $ServiceName.
# Returns a boolean $True or $False.
Function ServiceExists([string] $ServiceName) {
    [bool] $Return = $False
    # If you use just "Get-Service $ServiceName", it will return an error if 
    # the service didn't exist.  Trick Get-Service to return an array of 
    # Services, but only if the name exactly matches the $ServiceName.  
    # This way you can test if the array is emply.
    if ( Get-Service "$ServiceName*" -Include $ServiceName ) {
        $Return = $True
    }
    Return $Return
}

[bool] $thisServiceExists = ServiceExists "A Service Name"
$thisServiceExists 

But ravikanth has the best solution since the Get-WmiObject will not throw an error if the Service didn't exist. So I settled on using:

Function ServiceExists([string] $ServiceName) {
    [bool] $Return = $False
    if ( Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'" ) {
        $Return = $True
    }
    Return $Return
}

So to offer a more complete solution:

# Deletes a Service with a name as defined in $ServiceName.
# Returns a boolean $True or $False.  $True if the Service didn't exist or was 
# successfully deleted after execution.
Function DeleteService([string] $ServiceName) {
    [bool] $Return = $False
    $Service = Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'" 
    if ( $Service ) {
        $Service.Delete()
        if ( -Not ( ServiceExists $ServiceName ) ) {
            $Return = $True
        }
    } else {
        $Return = $True
    }
    Return $Return
}

1 Comment

I decided to do a speed comparison between Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" and Get-Service $serviceName -ErrorAction Ignore (which completely hides the error if the service doesn't exist) for completeness. I expected the Get-WmiObject might be faster because it doesn't throw an error. I was very wrong. Running each in a loop 100 times, Get-Service took 0.16 seconds while Get-WmiObject took 9.66 seconds. So Get-Service is 60x faster than Get-WmiObject.
13

To delete multiple services in Powershell 5.0, since remove service does not exist in this version

Run the below command

Get-Service -Displayname "*ServiceName*" | ForEach-object{ cmd /c  sc delete $_.Name}

Comments

12

More recent versions of PS have Remove-WmiObject. Beware of silent fails for $service.delete() ...

PS D:\> $s3=Get-WmiObject -Class Win32_Service -Filter "Name='TSATSvrSvc03'"

PS D:\> $s3.delete()
...
ReturnValue      : 2
...
PS D:\> $?
True
PS D:\> $LASTEXITCODE
0
PS D:\> $result=$s3.delete()

PS D:\> $result.ReturnValue
2

PS D:\> Remove-WmiObject -InputObject $s3
Remove-WmiObject : Access denied 
At line:1 char:1
+ Remove-WmiObject -InputObject $s3
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Remove-WmiObject], ManagementException
    + FullyQualifiedErrorId : RemoveWMIManagementException,Microsoft.PowerShell.Commands.RemoveWmiObject

PS D:\> 

For my situation I needed to be running 'As Administrator'

Comments

5

One could use Where-Object

if ((Get-Service | Where-Object {$_.Name -eq $serviceName}).length -eq 1) { "Service Exists" }

Comments

4

Combining Dmitri & dcx's answers I made this:

function Confirm-WindowsServiceExists($name)
{   
    if (Get-Service $name -ErrorAction SilentlyContinue)
    {
        return $true
    }
    return $false
}

function Remove-WindowsServiceIfItExists($name)
{   
    $exists = Confirm-WindowsServiceExists $name
    if ($exists)
    {    
        sc.exe \\server delete $name
    }       
}

Comments

4

For single PC:

if (Get-Service "service_name" -ErrorAction 'SilentlyContinue'){(Get-WmiObject -Class Win32_Service -filter "Name='service_name'").delete()}

else{write-host "No service found."}

Macro for list of PCs:

$name = "service_name"

$list = get-content list.txt

foreach ($server in $list) {

if (Get-Service "service_name" -computername $server -ErrorAction 'SilentlyContinue'){
(Get-WmiObject -Class Win32_Service -filter "Name='service_name'" -ComputerName $server).delete()}

else{write-host "No service $name found on $server."}

}

Comments

3

To check if a Windows service named MySuperServiceVersion1 exists, even when you might not be sure of its exact name, you could employ a wildcard, using a substring like so:

 if (Get-Service -Name "*SuperService*" -ErrorAction SilentlyContinue)
{
    # do something
}

Comments

3

PowerShell Core (v6+) now has a Remove-Service cmdlet.

I don't know about plans to back-port it to Windows PowerShell, where it is not available as of v5.1.

Example:

# PowerShell *Core* only (v6+)
Remove-Service someservice

Note that invocation fails if the service doesn't exist, so to only remove it if it currently exists, you could do:

# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
  Remove-Service $name
}

2 Comments

On PowerShell version 7, using the call to RemoteService gets the error "Remove-Service : The term 'Remove-Service' is not recognized as the name of a cmdlet, function, script file, or operable program"
@PedroVicente, note that In the context of remoting, even PowerShell 7 still targets Windows PowerShell on remote machines - see this answer.
2

Adapted this to take an input list of servers, specify a hostname and give some helpful output

            $name = "<ServiceName>"
            $servers = Get-content servers.txt

            function Confirm-WindowsServiceExists($name)
            {   
                if (Get-Service -Name $name -Computername $server -ErrorAction Continue)
                {
                    Write-Host "$name Exists on $server"
                    return $true
                }
                    Write-Host "$name does not exist on $server"
                    return $false
            }

            function Remove-WindowsServiceIfItExists($name)
            {   
                $exists = Confirm-WindowsServiceExists $name
                if ($exists)
                {    
                    Write-host "Removing Service $name from $server"
                    sc.exe \\$server delete $name
                }       
            }

            ForEach ($server in $servers) {Remove-WindowsServiceIfItExists($name)}

Comments

2
  • For PowerShell versions prior to v6, you can do this:

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
    
  • For v6+, you can use the Remove-Service cmdlet.

Observe that starting in Windows PowerShell 3.0, the cmdlet Get-WmiObject has been superseded by Get-CimInstance.

Comments

1

Windows Powershell 6 will have Remove-Service cmdlet. As of now the Github release shows PS v6 beta-9

Source: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-service?view=powershell-6

Comments

1

I know it's an old question but if someone is looking for one-liner:

On PS Version > 7.2

Wildcard search on the Name property

Get-Service *name* | Select-Object -First 1 | Remove-Service

Search the Display Name property

Get-Service -DisplayName "My Service Description" | Remove-Service

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.