Windows 서비스가 존재하는지 확인하고 PowerShell에서 삭제


148

현재 많은 Windows 서비스를 설치하는 배포 스크립트를 작성 중입니다.

서비스 이름은 버전이 지정되어 있으므로 새 서비스 설치의 일부로 이전 Windows 서비스 버전을 삭제하고 싶습니다.

PowerShell에서 가장 잘 수행 할 수있는 방법은 무엇입니까?

답변:


235

Remove-ServicePowershell 6.0까지 cmdlet 이 없으므로 WMI 또는 기타 도구를 사용할 수 있습니다 ( Remove-Service 문서 참조)

예를 들면 다음과 같습니다.

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

또는 sc.exe도구를 사용하여 :

sc.exe delete ServiceName

마지막으로 PowerShell 6.0에 액세스 할 수있는 경우 :

Remove-Service -Name ServiceName

2
이 예제의 관련 부분을 powershell로 옮길 수도 있습니다 (TransactedInstaller 클래스 사용) : eggheadcafe.com/articles/20060104.asp 그러나 ravikanth의 방법은 더 간단합니다.
JohnL

7
최신 버전의 PS에는 Remove-WmiObject가 있으며 $ service.delete ()에 대해 자동 실패에주의하십시오. 형식화 된 예제로 다른 답변을 추가했습니다.
Straff

1
간단히 말해, 최신 버전은 Powershell As Administrator를 실행하고 다음을 실행하는 것입니다. $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject
BamboOS

모든 사람의 정보에 대해 Straff의 답변은 "무음 실패에주의하십시오 $service.delete()"
sirdank

Windows PowerShell 3.0부터 Get-CmiInstance가 Get-WmiObject cmdlet을 대체했습니다. 그래서 요즘 당신은이 작업을 수행 할 수 있습니다Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
로즈버그 리냐 레스

122

작업에 적합한 도구를 사용하는 데 아무런 해가 없습니다 .Powershell에서 실행 중입니다.

sc.exe \\server delete "MyService" 

많은 의존성이없는 가장 신뢰할 수있는 방법.


55
sc 자체는 Set-Content의 별칭이므로 .exe 부분은 매우 중요합니다.
Tom Robinson

@tjrobinson 감사합니다 .exe. 귀하의 의견을 볼 때까지는 생략했습니다 . 이제는 나를 위해 일하고 있습니다.
gwin003

원격 컴퓨터에 대한 권한이있는 경우에만 유용합니다. 그렇지 않은 경우 (가장 안전한 환경 에서처럼) 작동하지 않으며 자격 증명 전달을 지원하는 항목이 필요합니다.
DaveStephens

\\server서비스가 로컬 인 경우 서버 이름 ( )은 생략됩니다.
jpmc26

1
이보다 쉽게 스크립트이기 때문에이 더 %$_
짜잔 Eliyah


21

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

그러나 서비스가 존재하지 않으면 Get-WmiObject에서 오류가 발생하지 않으므로 ravikanth가 최상의 솔루션을 제공합니다. 그래서 나는 다음을 사용하여 정착했다.

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
}

7
나는 사이의 속도를 비교하기로 결정 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는 Get-WmiObject보다 60 배 빠릅니다.
Simon Tewsi

13

최신 버전의 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:\> 

내 상황에서는 '관리자 권한으로'를 실행해야했습니다.


7

이 버전에는 제거 서비스가 없으므로 Powershell 5.0에서 여러 서비스를 삭제하려면

아래 명령을 실행하십시오.

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

5

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

4

Where-Object를 사용할 수 있습니다

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


3

이름 MySuperServiceVersion1이 정확한 Windows 서비스가 있는지 확인하려면 정확한 이름을 모르더라도 다음과 같은 하위 문자열을 사용하여 와일드 카드를 사용할 수 있습니다.

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

3

단일 PC의 경우 :

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

}

3

PowerShell Core ( v6 + )에는 이제 Remove-Servicecmdlet이 있습니다.

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
}


2

서버의 입력 목록을 가져 와서 호스트 이름을 지정하고 유용한 출력을 제공하도록 조정

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.