Kiểm tra xem dịch vụ Windows có tồn tại và xóa trong PowerShell không


148

Tôi hiện đang viết một kịch bản triển khai cài đặt một số dịch vụ Windows.

Tên dịch vụ được phiên bản, vì vậy tôi muốn xóa phiên bản dịch vụ Windows trước đó như một phần của bản cài đặt dịch vụ mới.

Làm cách nào tôi có thể làm điều này tốt nhất trong PowerShell?

Câu trả lời:


235

Bạn có thể sử dụng WMI hoặc các công cụ khác cho việc này vì không có Remove-Servicelệnh ghép ngắn cho đến khi Powershell 6.0 ( Xem tài liệu Xóa dịch vụ)

Ví dụ:

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

Hoặc với sc.execông cụ:

sc.exe delete ServiceName

Cuối cùng, nếu bạn có quyền truy cập vào PowerShell 6.0:

Remove-Service -Name ServiceName

2
Bạn cũng có thể chuyển phần có liên quan của ví dụ này sang powershell (sử dụng lớp TransactedInstaller): eggheadcafe.com/articles/20060104.asp Tuy nhiên phương pháp của rastaanth có lẽ đơn giản hơn.
JohnL

7
Các phiên bản gần đây hơn của PS có Remove-WmiObject và hãy cẩn thận với sự im lặng không thành công cho $ service.delete () - đã thêm một câu trả lời khác với các ví dụ được định dạng.
Straff

1
Nói tóm lại, hầu hết phiên bản cập nhật là chạy Powershell As Administrator và chạy theo sau: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject
BamboOS

Đối với thông tin của mọi người, câu trả lời của Straff cho biết "Coi chừng im lặng thất bại $service.delete()"
sirdank

Bắt đầu trong Windows PowerShell 3.0, lệnh ghép ngắn Get-WmiObject đã được thay thế bởi Get-CimInstance. Vì vậy, ngày nay bạn có thể làm điều này:Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
Rosberg Linhares

122

Không có hại trong việc sử dụng công cụ phù hợp cho công việc, tôi thấy việc chạy (từ Powershell)

sc.exe \\server delete "MyService" 

phương pháp đáng tin cậy nhất mà không có nhiều phụ thuộc.


55
Phần .exe rất quan trọng vì bản thân sc là bí danh cho Set-Content.
Tom Robinson

@tjrobinson Cảm ơn vì điều đó, tôi đã bỏ qua .execho đến khi tôi thấy bình luận của bạn. Bây giờ nó làm việc cho tôi.
gwin003

Điều này chỉ hữu ích nếu bạn có quyền đối với máy tính từ xa. Nếu không (như trong hầu hết các môi trường an toàn) thì điều này sẽ không hoạt động và bạn sẽ cần thứ gì đó hỗ trợ chuyển thông tin đăng nhập
DaveStephens

Tên máy chủ ( \\server) đơn giản được bỏ qua nếu dịch vụ là cục bộ.
jpmc26

1
điều này tốt hơn bởi vì nó dễ dàng hơn trong kịch bản với %$_
Chaim Eliyah

84

Nếu bạn chỉ muốn kiểm tra sự tồn tại của dịch vụ:

if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
    "service exists"
}

21

Tôi đã sử dụng giải pháp "-ErrorAction SilentlyContinue" nhưng sau đó gặp phải vấn đề là nó để lại ErrorRecord. Vì vậy, đây là một giải pháp khác để kiểm tra xem Dịch vụ có tồn tại bằng cách sử dụng "Dịch vụ nhận" hay không.

# 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 

Nhưng rastaanth có giải pháp tốt nhất vì Get-WmiObject sẽ không gây ra lỗi nếu Dịch vụ không tồn tại. Vì vậy, tôi quyết định sử dụng:

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

Vì vậy, để cung cấp một giải pháp đầy đủ hơn:

# 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
Tôi quyết định thực hiện so sánh tốc độ giữa Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"Get-Service $serviceName -ErrorAction Ignore(hoàn toàn che giấu lỗi nếu dịch vụ không tồn tại) để hoàn thiện. Tôi mong đợi Get-WmiObject có thể nhanh hơn vì nó không gây ra lỗi. Tôi đã rất sai. Chạy mỗi vòng trong 100 lần, Get-Service mất 0,16 giây trong khi Get-WmiObject mất 9,66 giây. Vì vậy, Get-Service nhanh hơn 60 lần so với Get-WmiObject.
Simon Tewsi

13

Các phiên bản gần đây hơn của PS có Remove-WmiObject. Cảnh giác với sự im lặng thất bại đối với $ 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:\> 

Đối với tình huống của tôi, tôi cần phải chạy 'Là quản trị viên'


7

Để xóa nhiều dịch vụ trong Powershell 5.0, vì dịch vụ xóa không tồn tại trong phiên bản này

Chạy lệnh dưới đây

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

5

Kết hợp câu trả lời của Dmitri & dcx Tôi đã thực hiện điều này:

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

Người ta có thể sử dụng Where-Object

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


3

Để kiểm tra xem dịch vụ Windows có tên MySuperServiceVersion1tồn tại hay không, ngay cả khi bạn có thể không chắc chắn về tên chính xác của nó, bạn có thể sử dụng ký tự đại diện, sử dụng chuỗi con như vậy:

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

3

Đối với PC đơn:

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

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

Macro cho danh sách 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 + ) hiện có Remove-Servicecmdlet .

Tôi không biết về kế hoạch sao lưu nó vào Windows PowerShell, nơi nó không có sẵn kể từ phiên bản 5.1.

Thí dụ:

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

Lưu ý rằng việc gọi không thành công nếu dịch vụ không tồn tại, do đó, chỉ xóa nó nếu nó hiện đang tồn tại, bạn có thể làm:

# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
  Remove-Service $name
}

3
  • Đối với các phiên bản PowerShell trước v6, bạn có thể thực hiện việc này:

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
  • Đối với v6 +, bạn có thể sử dụng lệnh ghép ngắn Xóa dịch vụ .

Quan sát rằng bắt đầu trong Windows PowerShell 3.0, lệnh ghép ngắn Get-WmiObject đã được thay thế bởi Get-CimInstance.


2

Điều chỉnh cái này để lấy danh sách đầu vào của máy chủ, chỉ định tên máy chủ và cung cấp một số đầu ra hữu ích

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.