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
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 6There'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" 6If you just want to check service existence:
if (Get-Service "My Service" -ErrorAction SilentlyContinue) { "service exists" } 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 } 1More 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'
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} One could use Where-Object
if ((Get-Service | Where-Object {$_.Name -eq $serviceName}).length -eq 1) { "Service Exists" }
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 } } 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."} } 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 } 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 } 2Adapted 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)} For PowerShell versions prior to v6, you can do this:
Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstanceFor 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.
Windows Powershell 6 will have Remove-Service cmdlet. As of now the Github release shows PS v6 beta-9
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