Periksa apakah ada layanan Windows dan hapus di PowerShell

148

Saat ini saya sedang menulis skrip penerapan yang menginstal sejumlah layanan Windows.

Nama layanan diversi, jadi saya ingin menghapus versi layanan Windows sebelumnya sebagai bagian dari pemasangan layanan baru.

Bagaimana cara terbaik saya melakukan ini di PowerShell?

Adrian Russell
sumber

Jawaban:

235

Anda dapat menggunakan WMI atau alat lain untuk ini karena tidak ada Remove-Servicecmdlet hingga Powershell 6.0 ( Lihat dokumen Remove-Service)

Sebagai contoh:

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

Atau dengan sc.exealat:

sc.exe delete ServiceName

Terakhir, jika Anda memiliki akses ke PowerShell 6.0:

Remove-Service -Name ServiceName
ravikanth
sumber
2
Anda juga dapat mem -port bagian yang relevan dari contoh ini ke PowerShell (gunakan kelas TransactedInstaller): eggheadcafe.com/articles/20060104.asp Namun metode ravikanth mungkin lebih sederhana.
JohnL
7
Versi terbaru dari PS memiliki Remove-WmiObject, dan waspadai silent gagal untuk $ service.delete () - telah menambahkan jawaban lain dengan contoh yang diformat.
Straff
1
Singkatnya, versi paling terbaru adalah menjalankan Powershell Sebagai Administrator dan menjalankan yang berikut: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject
BamboOS
Untuk informasi semua orang, jawaban Straff mengatakan "Waspadalah terhadap diam gagal untuk $service.delete()"
sirdank
Dimulai pada Windows PowerShell 3.0, cmdlet Get-WmiObject telah digantikan oleh Get-CimInstance. Jadi saat ini Anda dapat melakukan ini:Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
Rosberg Linhares
122

Tidak ada salahnya menggunakan alat yang tepat untuk pekerjaan itu, saya menemukan berjalan (dari Powershell)

sc.exe \\server delete "MyService" 

metode yang paling dapat diandalkan yang tidak memiliki banyak ketergantungan.

dcx
sumber
55
Bagian .exe sangat penting karena sc sendiri merupakan alias untuk Set-Content.
Tom Robinson
@tjrobinson Terima kasih untuk itu, saya telah menghilangkannya .exesampai saya melihat komentar Anda. Sekarang ini berfungsi untuk saya.
gwin003
Ini hanya berguna jika Anda memiliki hak untuk komputer jarak jauh. Jika tidak (seperti di sebagian besar lingkungan yang aman) ini tidak akan berfungsi dan Anda akan memerlukan sesuatu yang mendukung pengesahan kredensial
DaveStephens
Nama server ( \\server) dihilangkan begitu saja jika layanannya adalah lokal.
jpmc26
1
ini lebih baik karena lebih mudah ditulis dengan %dan$_
Chaim Eliyah
84

Jika Anda hanya ingin memeriksa keberadaan layanan:

if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
    "service exists"
}
Dmitry Fedorkov
sumber
21

Saya menggunakan solusi "-ErrorAction SilentlyContinue" tetapi kemudian mengalami masalah yang menyebabkan ErrorRecord tertinggal. Jadi, inilah solusi lain untuk hanya memeriksa apakah Layanan menggunakan "Dapatkan-Layanan".

# 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 

Tetapi ravikanth memiliki solusi terbaik karena Get-WmiObject tidak akan melakukan kesalahan jika Layanan tidak ada. Jadi saya memutuskan untuk menggunakan:

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

Jadi untuk menawarkan solusi yang lebih lengkap:

# 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
}
Kent
sumber
7
Saya memutuskan untuk melakukan perbandingan kecepatan antara Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"dan Get-Service $serviceName -ErrorAction Ignore(yang sepenuhnya menyembunyikan kesalahan jika layanan tidak ada) untuk kelengkapan. Saya berharap Get-WmiObject mungkin lebih cepat karena tidak menimbulkan kesalahan. Saya sangat salah. Menjalankan masing-masing dalam satu loop 100 kali, Get-Service mengambil 0,16 detik sementara Get-WmiObject mengambil 9,66 detik. Jadi Get-Service 60x lebih cepat dari Get-WmiObject.
Simon Tewsi
13

Versi terbaru dari PS memiliki Remove-WmiObject. Waspadalah terhadap silent gagal untuk $ 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:\> 

Untuk situasi saya, saya harus menjalankan 'Sebagai Administrator'

Straff
sumber
7

Untuk menghapus beberapa layanan di Powershell 5.0, karena layanan penghapusan tidak ada dalam versi ini

Jalankan perintah di bawah ini

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

Menggabungkan jawaban Dmitri & dcx saya buat ini:

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
    }       
}
Richard
sumber
4

Orang bisa menggunakan Where-Object

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

ShaneH
sumber
3

Untuk memeriksa apakah layanan Windows yang bernama MySuperServiceVersion1ada, bahkan ketika Anda mungkin tidak yakin nama persisnya, Anda bisa menggunakan wildcard, menggunakan substring seperti:

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

Untuk PC tunggal:

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

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

Makro untuk daftar 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."}

}
Ivan Temchenko
sumber
3

PowerShell Core ( v6 + ) sekarang memiliki Remove-Servicecmdlet .

Saya tidak tahu tentang rencana untuk kembali-port ke Windows PowerShell, di mana tidak tersedia pada v5.1.

Contoh:

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

Perhatikan bahwa doa gagal jika layanan tidak ada, jadi untuk hanya menghapusnya jika saat ini ada, Anda bisa melakukan:

# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
  Remove-Service $name
}
mklement0
sumber
3
  • Untuk versi PowerShell sebelum v6, Anda dapat melakukan ini:

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
  • Untuk v6 +, Anda dapat menggunakan cmdlet Hapus-Layanan .

Perhatikan bahwa mulai pada Windows PowerShell 3.0, cmdlet Get-WmiObject telah digantikan oleh Get-CimInstance.

Rosberg Linhares
sumber
2

Adaptasi ini untuk mengambil daftar input server, tentukan nama host dan berikan beberapa hasil yang bermanfaat

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