158 votes

Vérifiez si un service Windows existe et supprimez-le en PowerShell

Je suis actuellement en train d'écrire un script de déploiement qui installe un certain nombre de services Windows.

Les noms des services sont versionnés, donc je veux supprimer la version précédente du service Windows dans le cadre de l'installation du nouveau service.

Comment puis-je faire cela au mieux en PowerShell?

258voto

ravikanth Points 9573

Vous pouvez utiliser WMI ou d'autres outils pour cela car il n'y a pas de cmdlet Remove-Service jusqu'à Powershell 6.0 (Voir la documentation Remove-Service)

Par exemple:

$service = Get-WmiObject -Class Win32_Service -Filter "Name='nomduservice'"
$service.delete()

Ou avec l'outil sc.exe:

sc.exe delete NomDuService

Enfin, si vous avez accès à PowerShell 6.0:

Remove-Service -Name NomDuService

2 votes

Vous pourriez également porter la partie pertinente de cet exemple vers Powershell (utilisez la classe TransactedInstaller) : eggheadcafe.com/articles/20060104.asp Cependant, la méthode de Ravikanth est probablement plus simple.

8 votes

Des versions plus récentes de PS ont Remove-WmiObject, et méfiez-vous des échecs silencieux pour $service.delete() - j'ai ajouté une autre réponse avec des exemples formatés.

1 votes

En résumé, la version la plus récente consiste à exécuter Powershell en tant qu'Administrateur et à exécuter ce qui suit : $service = Get-WmiObject -Class Win32_Service -Filter "Name='servicename'" $service | Remove-WmiObject

129voto

dcx Points 331

Il n'y a pas de mal à utiliser le bon outil pour le travail, je trouve l'utilisation de sc.exe (via PowerShell) être la méthode la plus fiable avec peu de dépendances.

Local :

sc.exe delete "MyService"

Serveur distant :

sc.exe \\serveur delete "MyService"

58 votes

La partie .exe est très importante car sc par lui-même est un alias pour Set-Content.

0 votes

@tjrobinson Merci pour cela, j'avais omis le .exe jusqu'à ce que je voie votre commentaire. Maintenant ça fonctionne pour moi.

0 votes

Ceci est seulement utile si vous avez des droits sur l'ordinateur distant. Sinon (comme dans la plupart des environnements sécurisés), cela ne fonctionnera pas et vous aurez besoin de quelque chose qui prend en charge le passage des informations d'identification.

90voto

Dmitry Fedorkov Points 1680

Si vous voulez simplement vérifier l'existence du service:

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

22voto

Kent Points 81

J'ai utilisé la solution "-ErrorAction SilentlyContinue" mais j'ai ensuite rencontré le problème qu'elle laisse un ErrorRecord derrière. Voici donc une autre solution pour vérifier simplement si le Service existe en utilisant "Get-Service".

# Détermine si un Service existe avec un nom tel que défini dans $ServiceName.
# Renvoie un booléen $True ou $False.
Function ServiceExists([string] $ServiceName) {
    [bool] $Return = $False
    # Si vous utilisez simplement "Get-Service $ServiceName", cela renverra une erreur si
    # le service n'existait pas. Trompez Get-Service pour renvoyer un tableau de
    # Services, mais seulement si le nom correspond exactement à $ServiceName.
    # De cette façon, vous pouvez tester si le tableau est vide.
    if ( Get-Service "$ServiceName*" -Include $ServiceName ) {
        $Return = $True
    }
    Return $Return
}

[bool] $ceServiceExiste = ServiceExists "Un nom de service"
ceServiceExiste 

Mais ravikanth a la meilleure solution car Get-WmiObject ne jettera pas d'erreur si le Service n'existait pas. Donc j'ai opté pour utiliser:

Function ServiceExists([string] $ServiceName) {
    [bool] $Return = $False
    if ( Get-WmiObject -Class Win32_Service -Filter "Name='$ServiceName'" ) {
        $Return = $True
    }
    Return $Return
}

Donc pour offrir une solution plus complète:

# Supprime un service avec un nom tel que défini dans $ServiceName.
# Renvoie un booléen $True ou $False. $True si le Service n'existait pas ou a été
# supprimé avec succès après l'exécution.
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 votes

J'ai décidé de faire une comparaison de vitesse entre Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" et Get-Service $serviceName -ErrorAction Ignore (qui masque complètement l'erreur si le service n'existe pas) pour être exhaustif. Je m'attendais à ce que Get-WmiObject soit plus rapide car il ne génère pas d'erreurs. J'avais tort. En exécutant chaque commande dans une boucle 100 fois, Get-Service a pris 0.16 secondes tandis que Get-WmiObject a pris 9.66 secondes. Donc Get-Service est 60 fois plus rapide que Get-WmiObject.

3voto

Ifedi Okonkwo Points 53

Pour vérifier si un service Windows nommé MySuperServiceVersion1 existe, même lorsque vous n'êtes pas sûr de son nom exact, vous pouvez utiliser un joker, en utilisant une sous-chaîne de la sorte:

 if (Get-Service -Name "*SuperService*" -ErrorAction SilentlyContinue)
{
    # faire quelque chose
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X