Наразі пишу сценарій розгортання, який встановлює ряд служб Windows.
Назви служб узагальнені, тому я хочу видалити попередню версію служби Windows як частину встановлень нової служби.
Як мені найкраще це зробити в PowerShell?
Наразі пишу сценарій розгортання, який встановлює ряд служб Windows.
Назви служб узагальнені, тому я хочу видалити попередню версію служби Windows як частину встановлень нової служби.
Як мені найкраще це зробити в PowerShell?
Відповіді:
Ви можете використовувати WMI або інші інструменти для цього, оскільки немає Remove-Service
командлета, поки 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. Отже, ось ще одне рішення просто перевірити, чи існує Сервіс за допомогою "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
}
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 на 60 разів швидше, ніж Get-WmiObject.
Більш недавні версії 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}
Поєднуючи відповіді Дмитра та 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."}
}
PowerShell Core ( v6 + ) тепер має Remove-Service
командлет .
Я не знаю про плани повернути його в Windows PowerShell, де він не доступний з версії 5.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 + ви можете використовувати командлет Remove-Service .
Зауважте, що починаючи з Windows PowerShell 3.0, командлет 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 буде командлет Remove-Service . На даний момент випуск Github демонструє бета-9 PS v6