Obecnie piszę skrypt wdrażania, który instaluje szereg usług systemu Windows.
Nazwy usług są wersjonowane, dlatego chcę usunąć poprzednią wersję usługi systemu Windows w ramach instalacji nowej usługi.
Jak najlepiej to zrobić w PowerShell?
Obecnie piszę skrypt wdrażania, który instaluje szereg usług systemu Windows.
Nazwy usług są wersjonowane, dlatego chcę usunąć poprzednią wersję usługi systemu Windows w ramach instalacji nowej usługi.
Jak najlepiej to zrobić w PowerShell?
Odpowiedzi:
Możesz użyć do tego WMI lub innych narzędzi, ponieważ nie ma polecenia Remove-Service
cmdlet aż do Powershell 6.0 ( zobacz dokument Remove-Service)
Na przykład:
$service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'"
$service.delete()
Lub za pomocą sc.exe
narzędzia:
sc.exe delete ServiceName
Wreszcie, jeśli masz dostęp do programu 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
Nie ma nic złego w używaniu odpowiedniego narzędzia do pracy, uważam, że działa (z Powershell)
sc.exe \\server delete "MyService"
najbardziej niezawodna metoda, która nie ma wielu zależności.
.exe
komentarz, dopóki nie zobaczyłem twojego komentarza. Teraz to działa dla mnie.
\\server
) jest po prostu pomijana, jeśli usługa jest lokalna.
%
i$_
Jeśli chcesz tylko sprawdzić istnienie usługi:
if (Get-Service "My Service" -ErrorAction SilentlyContinue)
{
"service exists"
}
Użyłem rozwiązania „-ErrorAction SilentlyContinue”, ale później napotkałem problem polegający na tym, że pozostawia za sobą ErrorRecord. Oto kolejne rozwiązanie pozwalające po prostu sprawdzić, czy Usługa istnieje, za pomocą funkcji „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
Ale ravikanth ma najlepsze rozwiązanie, ponieważ Get-WmiObject nie zgłosi błędu, jeśli usługa nie istnieje. Więc zdecydowałem się na użycie:
Function ServiceExists([string] $ServiceName) {
[bool] $Return = $False
if ( Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'" ) {
$Return = $True
}
Return $Return
}
Aby zaoferować bardziej kompletne rozwiązanie:
# 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'"
i Get-Service $serviceName -ErrorAction Ignore
(co całkowicie ukrywa błąd, jeśli usługa nie istnieje) dla kompletności. Spodziewałem się, że Get-WmiObject może być szybszy, ponieważ nie zgłasza błędu. Bardzo się myliłem. Uruchomienie każdego w pętli 100 razy, Get-Service zajęło 0,16 sekundy, a Get-WmiObject 9,66 sekundy. Więc Get-Service jest 60x szybszy niż Get-WmiObject.
Nowsze wersje PS mają Remove-WmiObject. Uważaj na ciche niepowodzenia $ 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:\>
W mojej sytuacji potrzebowałem uruchomić „Jako administrator”
Aby usunąć wiele usług w programie PowerShell 5.0, ponieważ usługa usuwania nie istnieje w tej wersji
Uruchom poniższe polecenie
Get-Service -Displayname "*ServiceName*" | ForEach-object{ cmd /c sc delete $_.Name}
Łącząc odpowiedzi Dmitri i dcx, zrobiłem to:
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
}
}
Aby sprawdzić, czy usługa Windows o nazwie MySuperServiceVersion1
istnieje, nawet jeśli nie jesteś pewien jej dokładnej nazwy, możesz użyć symbolu wieloznacznego, używając podłańcucha takiego jak ten:
if (Get-Service -Name "*SuperService*" -ErrorAction SilentlyContinue)
{
# do something
}
Dla jednego komputera:
if (Get-Service "service_name" -ErrorAction 'SilentlyContinue'){(Get-WmiObject -Class Win32_Service -filter "Name='service_name'").delete()}
else{write-host "No service found."}
Makro do listy komputerów:
$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 + ) ma teraz polecenie Remove-Service
cmdlet .
Nie wiem o planach back-portu go do systemu Windows PowerShell, gdzie jest nie dostępna od v5.1.
Przykład:
# PowerShell *Core* only (v6+)
Remove-Service someservice
Pamiętaj, że wywołanie kończy się niepowodzeniem, jeśli usługa nie istnieje, więc aby usunąć ją tylko wtedy, gdy obecnie istnieje, możesz wykonać:
# PowerShell *Core* only (v6+)
$name = 'someservice'
if (Get-Service $name -ErrorAction Ignore) {
Remove-Service $name
}
W przypadku wersji programu PowerShell wcześniejszych niż wersja 6 można to zrobić:
Stop-Service 'YourServiceName'; Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | Remove-CimInstance
W przypadku wersji 6+ można użyć polecenia cmdlet Remove-Service .
Zwróć uwagę, że począwszy od programu Windows PowerShell 3,0, polecenie cmdlet Get-WmiObject zostało zastąpione przez Get-CimInstance.
Zaadaptowano to, aby pobrać listę wejściową serwerów, określić nazwę hosta i podać pomocne wyniki
$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 będzie miał cmdlet Remove-Service . Jak na razie wydanie Github pokazuje PS v6 beta-9