ตรวจสอบว่ามีบริการ Windows อยู่และลบใน PowerShell หรือไม่


148

ฉันกำลังเขียนสคริปต์การปรับใช้ที่ติดตั้งบริการ Windows จำนวนหนึ่ง

ชื่อบริการได้รับการกำหนดเวอร์ชันดังนั้นฉันต้องการลบรุ่นบริการของ Windows ก่อนหน้าซึ่งเป็นส่วนหนึ่งของการติดตั้งของบริการใหม่

ฉันจะทำสิ่งนี้ได้ดีที่สุดใน PowerShell

คำตอบ:


235

คุณสามารถใช้ WMI หรือเครื่องมืออื่น ๆ สำหรับสิ่งนี้เนื่องจากไม่มีRemove-Servicecmdlet จนถึง Powershell 6.0 ( ดูเอกสารการลบบริการ)

ตัวอย่างเช่น:

$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 ในฐานะผู้ดูแลระบบและเรียกใช้ดังต่อไปนี้: $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject
BamboOS

สำหรับข้อมูลของทุกคนคำตอบของ Straff บอกว่า "ระวังความเงียบล้มเหลว$service.delete()"
sirdank

เริ่มต้นใน Windows PowerShell 3.0 cmdlet 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
ส่วน. exe มีความสำคัญอย่างยิ่งเนื่องจาก sc ในตัวของมันเองนั้นเป็นนามแฝงสำหรับชุดเนื้อหา
Tom Robinson

@tjrobinson ขอบคุณสำหรับสิ่งที่ฉันได้ละเว้น.exeจนกว่าฉันจะเห็นความคิดเห็นของคุณ ตอนนี้มันใช้ได้สำหรับฉัน
gwin003

สิ่งนี้มีประโยชน์ก็ต่อเมื่อคุณมีสิทธิ์ในคอมพิวเตอร์ระยะไกล หากไม่ (เช่นในสภาพแวดล้อมที่ปลอดภัยที่สุด) สิ่งนี้จะไม่ทำงานและคุณจะต้องมีสิ่งที่รองรับการส่งผ่านข้อมูลประจำตัว
DaveStephens

ชื่อเซิร์ฟเวอร์ ( \\server) จะถูกตัดออกหากบริการเป็นแบบโลคัล
jpmc26

1
นี้จะดีกว่าเพราะมันเป็นสคริปต์ได้ง่ายขึ้นด้วย%และ$_
ไคม์ Eliyah

84

หากคุณต้องการตรวจสอบการมีอยู่ของบริการ:

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

21

ฉันใช้โซลูชัน "-ErrorAction SilentlyContinue" แต่หลังจากนั้นก็พบปัญหาที่ทำให้ ErrorRecord อยู่ด้านหลัง ดังนั้นนี่เป็นอีกวิธีการหนึ่งในการตรวจสอบว่าบริการมีอยู่โดยใช้ "รับบริการ"

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

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


3

ในการตรวจสอบว่ามีบริการ Windows ชื่อMySuperServiceVersion1อยู่หรือไม่แม้ว่าคุณอาจไม่แน่ใจในชื่อที่แน่นอนคุณสามารถใช้ wildcard โดยใช้ซับสตริงดังนี้

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

3

สำหรับพีซีเครื่องเดียว:

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

}

3

PowerShell หลัก ( v6 + ) ตอนนี้มีcmdletRemove-Service

ฉันไม่รู้เกี่ยวกับแผนการสำรองพอร์ตไปยังWindows PowerShell ซึ่งไม่สามารถใช้งานได้ตั้งแต่ v5.1

ตัวอย่าง:

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

โปรดทราบว่าการเรียกใช้ล้มเหลวหากไม่มีบริการอยู่ดังนั้นหากต้องการลบออกหากมีอยู่ในปัจจุบันคุณสามารถทำได้:

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

3
  • สำหรับ PowerShell เวอร์ชั่นก่อน v6 คุณสามารถทำได้:

    Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
  • สำหรับ v6 + คุณสามารถใช้cmdlet ที่เอาออกบริการ

สังเกตว่าเริ่มต้นใน Windows PowerShell 3.0 cmdlet Get-WmiObjectถูกแทนที่โดย Get-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.