检查是否存在 Windows 服务并在 PowerShell 中删除

我目前正在编写一个安装许多 Windows 服务的部署脚本。

服务名称是版本化的,因此我想删除以前的 Windows 服务版本,作为新服务安装的一部分。

我如何在 PowerShell 中做到最好?

252847 次浏览

您可以使用 WMI 或其他工具,因为在 Powershell 6.0(请参阅删除-服务文档)之前没有 Remove-Service cmdlet

例如:

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

或者使用 sc.exe工具:

sc.exe delete ServiceName

最后,如果你能使用 PowerShell 6.0:

Remove-Service -Name ServiceName

使用正确的工具完成工作没有坏处,我发现运行(从 Powershell)

sc.exe \\server delete "MyService"

没有很多依赖项的最可靠的方法。

如果您只想检查服务是否存在:

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

我使用了“-ErrorAction SilentlyContinue”解决方案,但后来遇到了留下 ErrorRecord 的问题。因此,这里有另一个解决方案,只是检查服务是否存在使用“获取服务”。

# 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

但是 ravikanth 有最好的解决方案,因为如果服务不存在,Get-WmiObject 不会抛出错误。所以我决定用:

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

因此,为了提供一个更完整的解决方案:

# 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
}

结合 Dmitri 和 dcx 的回答,我做了这样一个决定:

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
}
}

将其改编为获取服务器的输入列表、指定主机名并提供一些有用的输出

            $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)}

可以使用 Where-Object

如果((Get-Service | Where-Object { $_. Name-eq $serviceName }) . length-eq 1){ “服务存在” }

要检查名为 MySuperServiceVersion1的 Windows 服务是否存在,即使您可能不确定其确切名称,也可以使用通配符,使用如下子字符串:

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

个人电脑:

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


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

个人电脑列表的宏:

$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."}


}

最新版本的 PS 有 delete-WmiObject。

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:\>

对于我的情况,我需要运行’作为管理员’

Windows PowerShell 6将使用 删除-服务 cmdlet。 到目前为止,Github 发布版本显示了 PS v6 beta-9

来源: < a href = “ https://Learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-service? view = powershell-6”rel = “ nofollow noReferrer”> https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-service?view=powershell-6

删除 Powershell 5.0中的多个服务,因为这个版本中不存在删除服务

运行以下命令

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

PowerShell 核心 (V6 + )现在有一个 Remove-Service cmdlet

我不知道有没有计划把它后端移植到 窗户 PowerShell,在那里它在5.1版本中是 没有可用的。

例如:

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

请注意,如果服务不存在,调用将失败,因此只有在当前存在时才删除它,您可以这样做:

# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
Remove-Service $name
}
  • 对于 V6之前的 PowerShell 版本,您可以这样做:

    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.

我知道这是一个老问题,但如果有人在寻找俏皮话:

关于 PS 版本 > 7.2

对 Name 属性进行通配符搜索

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

搜索“显示名称”属性

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