ฉันกำลังเขียนสคริปต์การปรับใช้ที่ติดตั้งบริการ Windows จำนวนหนึ่ง
ชื่อบริการได้รับการกำหนดเวอร์ชันดังนั้นฉันต้องการลบรุ่นบริการของ Windows ก่อนหน้าซึ่งเป็นส่วนหนึ่งของการติดตั้งของบริการใหม่
ฉันจะทำสิ่งนี้ได้ดีที่สุดใน PowerShell
ฉันกำลังเขียนสคริปต์การปรับใช้ที่ติดตั้งบริการ Windows จำนวนหนึ่ง
ชื่อบริการได้รับการกำหนดเวอร์ชันดังนั้นฉันต้องการลบรุ่นบริการของ Windows ก่อนหน้าซึ่งเป็นส่วนหนึ่งของการติดตั้งของบริการใหม่
ฉันจะทำสิ่งนี้ได้ดีที่สุดใน PowerShell
คำตอบ:
คุณสามารถใช้ WMI หรือเครื่องมืออื่น ๆ สำหรับสิ่งนี้เนื่องจากไม่มีRemove-Service
cmdlet จนถึง 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
$service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'"
$service | Remove-WmiObject
$service.delete()
"
Stop-Service 'servicename'; Get-CimInstance -ClassName Win32_Service -Filter "Name='servicename'" | Remove-CimInstance
ไม่มีอันตรายใด ๆ ในการใช้เครื่องมือที่เหมาะสมสำหรับงานฉันพบว่าทำงาน (จาก Powershell)
sc.exe \\server delete "MyService"
วิธีการที่เชื่อถือได้มากที่สุดที่ไม่มีการขึ้นต่อกันมากมาย
.exe
จนกว่าฉันจะเห็นความคิดเห็นของคุณ ตอนนี้มันใช้ได้สำหรับฉัน
\\server
) จะถูกตัดออกหากบริการเป็นแบบโลคัล
%
และ$_
หากคุณต้องการตรวจสอบการมีอยู่ของบริการ:
if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
"service exists"
}
ฉันใช้โซลูชัน "-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
}
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 เท่า
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:\>
สำหรับสถานการณ์ของฉันฉันต้องเรียกใช้ 'ในฐานะผู้ดูแลระบบ'
หากต้องการลบบริการหลายรายการใน Powershell 5.0 เนื่องจากบริการลบไม่มีอยู่ในรุ่นนี้
เรียกใช้คำสั่งด้านล่าง
Get-Service -Displayname "*ServiceName*" | ForEach-object{ cmd /c sc delete $_.Name}
การรวมคำตอบของ 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
}
}
สามารถใช้ Where-Object
if ((Get-Service | Where-Object {$_.Name -eq $serviceName}).length -eq 1) {
"Service Exists"
}
ในการตรวจสอบว่ามีบริการ Windows ชื่อMySuperServiceVersion1
อยู่หรือไม่แม้ว่าคุณอาจไม่แน่ใจในชื่อที่แน่นอนคุณสามารถใช้ wildcard โดยใช้ซับสตริงดังนี้
if (Get-Service -Name "*SuperService*" -ErrorAction SilentlyContinue)
{
# do something
}
สำหรับพีซีเครื่องเดียว:
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."}
}
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
}
สำหรับ 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
ดัดแปลงเพื่อใช้รายการอินพุตของเซิร์ฟเวอร์ระบุชื่อโฮสต์และให้ผลลัพธ์ที่เป็นประโยชน์
$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)}
Windows Powershell 6 จะมีบริการลบ cmdlet ณ ตอนนี้ Github รีลีสแสดง PS v6 beta-9