Windowsサービスが存在するかどうかを確認し、PowerShellで削除する


148

現在、いくつかのWindowsサービスをインストールするデプロイメントスクリプトを書いています。

サービス名はバージョン管理されているので、新しいサービスのインストールの一部として、以前のWindowsサービスバージョンを削除します。

PowerShellでこれを行うにはどうすればよいですか?

回答:


235

Remove-ServicePowershell 6.0までコマンドレットがないため、WMIまたはその他のツールを使用できます(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

2
この例の関連部分をpowershellに移植することもできます(TransactedInstallerクラスを使用します)。eggheadcafe.com / articles / 20060104.aspただし、ravikanthの方法はおそらくより簡単です。
JohnL 2011

7
PSの最近のバージョンにはRemove-WmiObjectがあり、$ service.delete()のサイレント失敗に注意-フォーマットされた例で別の答えを追加しました。
2016年

1
要するに、ほとんどの最新バージョンには、次のPowerShellのようAdministratorを実行し、実行することです: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject

みんなの情報については、Straffの回答は「サイレントに注意して失敗する$service.delete()
sirdank

Windows PowerShell 3.0以降、コマンドレットGet-WmiObjectはGet-CimInstanceに置き換えられました。したがって、今日これを行うことができます:Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
Rosberg Linhares

122

仕事に適したツールを使用しても害はありません(Powershellから)

sc.exe \\server delete "MyService" 

多くの依存関係を持たない最も信頼できる方法。


55
sc自体はSet-Contentのエイリアスであるため、.exeの部分は非常に重要です。
トムロビンソン

@tjrobinsonそのおかげで、.exeあなたのコメントを見るまでは省略していました。今、私のために働いています。
gwin003 2013年

これは、リモートコンピュータに対する権限がある場合にのみ役立ちます。そうでない場合(ほとんどの安全な環境のように)、これは機能せず、資格情報の受け渡しをサポートするものが必要になります
DaveStephens

\\serverサービスがローカルの場合、サーバー名()は省略されます。
jpmc26 2017年

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 

ただし、Serviceが存在しなくても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 2017年

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

という名前のWindowsサービスがMySuperServiceVersion1存在するかどうかを確認するには、正確な名前がわからない場合でも、次のような部分文字列を使用してワイルドカードを使用できます。

 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 Corev6 +)にRemove-Serviceコマンドレットが追加されました

Windows 5.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
}

3
  • v6より前のバージョンのPowerShellの場合、これを行うことができます。

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
  • v6 +の場合、Remove-Serviceコマンドレットを使用できます。

Windows PowerShell 3.0以降では、コマンドレットGet-WmiObjectGet-CimInstanceに置き換えられていることに注目してください。


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.