Ответ 1
Для этого вам необходимо использовать WMI, так как отсутствует командлет Remove-Service
Например,
$service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'"
$service.delete()
В настоящее время я пишу развертывание script, которое устанавливает несколько служб Windows.
Имена служб версируются, поэтому я хочу удалить предыдущую версию службы Windows как часть установки новой службы.
Как лучше всего сделать это в PowerShell?
Для этого вам необходимо использовать WMI, так как отсутствует командлет Remove-Service
Например,
$service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'"
$service.delete()
Нет никакого вреда в использовании правильного инструмента для работы, я нахожу работу (из Powershell)
sc.exe \\server delete "MyService"
самый надежный метод, который не имеет много зависимостей.
Если вы просто хотите проверить существование службы:
if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
"service exists"
}
Я использовал решение "-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
Но 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
}
В более поздних версиях 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:\>
Для моей ситуации мне нужно было запустить "Как администратор"
Объединяя ответы 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
}
}
Чтобы проверить, существует ли служба Windows с именем MySuperServiceVersion1
, даже если вы не уверены в ее точном имени, вы можете использовать подстановочный знак, используя такую подстроку:
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."}
}
Адаптировано для ввода списка серверов, указать имя хоста и дать полезный вывод
$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)}
Можно использовать Where-Object
if ((Get-Service | Where-Object {$_.Name -eq $serviceName}).length -eq 1) {
"Service Exists"
}
В Windows Powershell 6 будет установлен командлет Remove-Service. На данный момент релиз Github показывает PS v6 beta-9
Чтобы удалить несколько служб в Powershell 5.0, так как в этой версии нет службы удаления
Запустите команду
Get-Service -Displayname "*ServiceName*" | ForEach-object{ cmd /c sc delete $_.Name}
PowerShell Core (v6 +) теперь имеет Remove-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
}
В моем случае проблема заключалась в том, что служба застряла в состоянии "Запуск", и Windows не удалит службу до ее завершения. В этом случае вам нужно прекратить обслуживание вручную. Я выполнил следующие шаги:
sc queryex {{servicename}}
, где имя службы - это короткое имя службы (а не отображаемое имя). Обратите внимание на PID.taskkill /f /pid {{PID}}
Служба затем завершается и удаляется мгновенно.