Проверете дали съществува услуга на Windows и изтрийте в PowerShell

В момента пиша скрипт за внедряване, който инсталира няколко услуги на Windows.

Имената на услугите са с версии, така че искам да изтрия предишната версия на услугата на Windows като част от инсталациите на новата услуга.

Как най-добре мога да направя това в PowerShell?


person Adrian Russell    schedule 11.02.2011    source източник


Отговори (14)


Можете да използвате WMI или други инструменти за това, тъй като няма Remove-Service cmdlet до Powershell 6.0 (Вижте Remove-Service doc)

Например:

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

Или с инструмента sc.exe:

sc.exe delete ServiceName

И накрая, ако имате достъп до PowerShell 6.0:

Remove-Service -Name ServiceName
person ravikanth    schedule 11.02.2011
comment
Можете също да пренесете съответната част от този пример към powershell (използвайте класа TransactedInstaller): eggheadcafe.com /articles/20060104.asp Методът на ravikanth обаче вероятно е по-прост. - person JohnL; 11.02.2011
comment
По-новите версии на PS имат Remove-WmiObject и се пазете от безшумни грешки за $service.delete() - добавиха още един отговор с форматирани примери. - person Straff; 04.05.2016
comment
Накратко, най-актуалната версия е да стартирате Powershell като администратор и да изпълните следното: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject - person BamboOS; 28.06.2017
comment
За информация на всички, отговорът на Straff казва Пазете се от тихи грешки за $service.delete() - person sirdank; 06.07.2017
comment
Започвайки от Windows PowerShell 3.0, cmdlet Get-WmiObject е заменен от Get-CimInstance. Така че днес можете да направите това: Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance - person Rosberg Linhares; 19.04.2018

Няма нищо лошо в използването на правилния инструмент за работата, смятам, че работи (от Powershell)

sc.exe \\server delete "MyService" 

най-надеждният метод, който няма много зависимости.

person dcx    schedule 11.02.2011
comment
Частта .exe е много важна, тъй като sc сам по себе си е псевдоним за Set-Content. - person Tom Robinson; 29.08.2013
comment
@tjrobinson Благодаря за това, бях пропуснал .exe, докато не видях коментара ви. Сега работи за мен. - person gwin003; 22.10.2013
comment
Това е полезно само ако имате права на отдалечения компютър. Ако не (както в повечето сигурни среди), това няма да работи и ще ви трябва нещо, което поддържа предаване на идентификационни данни - person DaveStephens; 03.11.2015
comment
Името на сървъра (\\server) просто се пропуска, ако услугата е локална. - person jpmc26; 25.03.2017
comment
това е по-добре, защото е по-лесно скриптово с % и $_ - person Chaim Eliyah; 20.07.2017
comment
Това беше много полезно, когато просто трябваше бързо да изчистя локална услуга, инсталирана на моя лаптоп. Благодаря ти! - person Jay S; 14.11.2017

Ако просто искате да проверите съществуването на услугата:

if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
    "service exists"
}
person Dmitry Fedorkov    schedule 13.06.2012

Използвах решението „-ErrorAction SilentlyContinue“, но по-късно се натъкнах на проблема, че оставя ErrorRecord след себе си. И така, ето още едно решение просто да проверите дали услугата съществува с помощта на „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 

Но 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
}
person Kent    schedule 18.06.2013
comment
Реших да направя сравнение на скоростта между Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" и Get-Service $serviceName -ErrorAction Ignore (което напълно скрива грешката, ако услугата не съществува) за пълнота. Очаквах, че Get-WmiObject може да е по-бърз, защото не извежда грешка. Много грешах. Изпълнявайки всеки в цикъл 100 пъти, Get-Service отне 0,16 секунди, докато Get-WmiObject отне 9,66 секунди. Така Get-Service е 60 пъти по-бърз от Get-WmiObject. - person Simon Tewsi; 27.03.2017

По-новите версии на PS имат Remove-WmiObject. Пазете се от тихи грешки за $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:\> 

За моята ситуация трябваше да работя „Като администратор“

person Straff    schedule 03.05.2016

За да изтриете няколко услуги в Powershell 5.0, тъй като услугата за премахване не съществува в тази версия

Изпълнете командата по-долу

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

Комбинирайки отговорите на Дмитрий и 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
    }       
}
person Richard    schedule 24.01.2014

Може да се използва Where-Object

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

person ShaneH    schedule 21.10.2014

За да проверите дали услуга на Windows с име MySuperServiceVersion1 съществува, дори когато може да не сте сигурни в точното й име, можете да използвате заместващ знак, като използвате подниз като този:

 if (Get-Service -Name "*SuperService*" -ErrorAction SilentlyContinue)
{
    # do something
}
person Ifedi Okonkwo    schedule 25.10.2014

За един компютър:

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

}
person Ivan Temchenko    schedule 22.09.2015


  • За версии на PowerShell преди v6 можете да направите следното:

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
    
  • За v6+ можете да използвате кратката команда Remove-Service.

Забележете, че започвайки с Windows PowerShell 3.0, кратката команда Get-WmiObject е заменена от Get-CimInstance.

person Rosberg Linhares    schedule 01.03.2018

Адаптирано това, за да вземе входен списък със сървъри, да посочи име на хост и да даде полезен резултат

            $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)}
person Gerald    schedule 29.04.2014

Windows Powershell 6 ще има cmdlet Remove-Service. Към момента изданието на Github показва PS v6 beta-9

Източник: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-service?view=powershell-6

person Gagan    schedule 10.11.2017