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

检查Windows服务是否存在,并在PowerShell中删除,powershell,windows-services,Powershell,Windows Services,我目前正在编写一个部署脚本,用于安装许多Windows服务 服务名称已版本化,因此我希望在安装新服务时删除以前的Windows服务版本 如何在PowerShell中最好地执行此操作?您可以使用WMI或其他工具来执行此操作,因为在PowerShell 6.0之前没有删除服务cmdlet( 例如: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service.delete() 或者使用sc.e

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

服务名称已版本化,因此我希望在安装新服务时删除以前的Windows服务版本


如何在PowerShell中最好地执行此操作?

您可以使用WMI或其他工具来执行此操作,因为在PowerShell 6.0之前没有
删除服务
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)


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

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

if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
    "service exists"
}
我使用了“-ErrorAction SilentlyContinue”解决方案,但后来遇到了一个问题,即它会留下错误记录。因此,这里有另一个解决方案,可以使用“Get Service”检查服务是否存在

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

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)}
$name=“”
$servers=Get content servers.txt
函数确认WindowsServiceExists($name)
{   
if(获取服务-名称$Name-计算机名称$server-错误操作继续)
{
写入主机“$name存在于$server上”
返回$true
}
写入主机“$name在$server上不存在”
返回$false
}
函数删除WindowsServiceIfItExists($name)
{   
$exists=确认WindowsServiceExists$name
如果($存在)
{    
写入主机“从$server中删除服务$name”
sc.exe\\$server删除$name
}       
}
ForEach($servers中的服务器){删除WindowsServiceIfItExists($name)}

可以使用Where对象


if((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."}
用于PC列表的宏:

$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的最新版本已删除WmiObject。请注意$service.delete()的静默失败


对于我的情况,我需要以“管理员”身份运行Windows Powershell 6将具有删除服务cmdlet。 到目前为止,Github发行版显示了PS v6 beta-9


来源:

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

运行下面的命令

Get-Service -Displayname "*ServiceName*" | ForEach-object{ cmd /c  sc delete $_.Name}
v6+)现在有一个

我不知道是否有计划将其移植到Windows PowerShell,因为从v5.1开始,Windows PowerShell就不可用

例如:

# 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
    
  • 对于v6+,您可以使用


请注意,从Windows PowerShell 3.0开始,已被Get-CimInstance取代。

您也可以将此示例的相关部分移植到PowerShell(使用TransactiveInstaller类):但是ravikanth的方法可能更简单。PS的较新版本已删除WmiObject,并且要注意$service的静默失败。delete()-添加了另一个带有格式示例的答案。简言之,最新版本是以管理员身份运行Powershell,并运行以下命令:
$service=Get WmiObject-Class Win32_service-Filter“Name='servicename'”
$service |删除WmiObject
,供所有人参考,Straff的回答说“注意,
$service.delete()
”从Windows PowerShell 3.0开始,cmdlet Get-WmiObject已被Get-CimInstance取代。因此,现在您可以执行以下操作:
停止服务'servicename';Get-CimInstance-类名Win32_服务-筛选器“Name='servicename'“| Remove CimInstance
该.exe部分非常重要,因为sc本身就是集合内容的别名。@tjrobinson为此表示感谢,在看到您的评论之前,我省略了
.exe
。现在它对我有效。这仅在您拥有远程计算机的权限时才有用。如果没有权限(就像在大多数安全环境中一样)这将不起作用,您将需要一些支持传入凭据的内容如果服务是本地的,则服务器名称(
\\server
)将被省略。这更好,因为使用
%
$\uu
更容易编写脚本。我决定在
Get WMIOObject-Class Win32\u service-Filter之间进行速度比较“Name='$serviceName'
获取服务$serviceName-ErrorAction Ignore
(如果服务不存在,则完全隐藏错误)为了完整性。我预计Get-WmiObject可能会更快,因为它不会引发错误。我大错特错。在循环中运行每个对象100次,Get-Service需要0.16秒,Get-WmiObject需要9.66秒。因此Get-Service比Get-WmiObject快60倍。
# PowerShell *Core* only (v6+)
Remove-Service someservice
# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
  Remove-Service $name
}
Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance