Comment exécuter un script PowerShell comme service ?

I. Présentation

Si vous souhaitez qu'un script PowerShell s'exécute en arrière-plan et façon continue sur votre serveur, et qu'il démarre automatiquement lorsque vous lors d'un (re)démarrage, exécuter le script en tant que service Windows est une bonne solution. Il devient aisé de faire tourner un script 24/7 🙂

Pour parvenir à créer un service qui exécute un script PS1, on va s'appuyer sur un outil très pratique : NSSM (Non-Sucking Service Manager). Un peu dans le même esprit que l'outil intégré SRVANY intégré à Windows. Le site officiel : NSSM

En guise d'exemple, je vais exécuter un script qui surveille un dossier et qui m'envoie un e-mail s'il y a un changement sur un fichier contenu dans ce dossier (création / modification / suppression). D'ailleurs, je vous propose un article sur le sujet pour la fin de semaine prochaine.

II. Installer NSSM en PowerShell

Nous allons récupérer NSSM sur notre machine à partir de l'installeur Choco. Si besoin, vous pouvez installer Choco de cette façon en PowerShell (saisissez "choco" dans une console et si la commande n'est pas reconnue c'est qu'il n'est pas installée) :

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

Par la suite, pensez à mettre Choco de temps en temps si vous continuez de l'utiliser avec la commande suivante :

choco upgrade chocolatey

Maintenant, on va pouvoir installer NSSM simplement avec cette commande :

choco install nssm -y

L'option "y" permet d'accepter automatiquement les conditions d'installation.

Plus d'infos sur le paquet NSSM de Choco

Maintenant que NSSM est installé, rentrons dans le vif du sujet.

III. Créer un service à partir d'un script PowerShell

Le bout de code que je vais lancer en tant que service est celui ci-dessous, libre à vous d'avoir le code que vous voulez dans le script. Il faut tout de même que ce soit un script qui tourne en continue ou avec des actions répétées, s'il s'agit d'une exécution unique il n'y a pas d'intérêt à l'exécuter en tant que service.

Voici le code d'exemple :

watch -location "C:\Watch" | Foreach{

  Add-Content -Value "$(Get-Date -Format yyyyMMdd#HHmm) - $($_.Operation) - Evénement sur $($_.Path)" -Path "C:\Scripting\Logs\watch.log"

}

On va commencer par déclarer trois variables : $PathNSSM (chemin vers l'exécutable NSSM), $PathPowerShell (chemin vers l'exécutable PowerShell) et $PathScript (chemin vers le .ps1 à exécuter avec le service).

Ce qui nous donne le code ci-dessous, dont vous devez adapter seulement $PathScript :

$PathNSSM = (Get-Command NSSM).Source
$PathPowerShell = (Get-Command Powershell).Source
$PathScript = "C:\Scripting\it-connect.ps1"

En complément, on va déclarer la variable $ServiceName qui va contenir le nom de notre service :

$ServiceName = "Watch"

Enfin, la variable $ServiceArguments va stocker la chaîne complète d'arguments à mettre à la suite de "powershell.exe", ce qui comprendra notamment le chemin du script ($PathScript) et le fait de ne pas utiliser de profil personnalisé :

$ServiceArguments = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $PathScript

Enfin, on va exécuter la commande qui va créer le service à l'aide de NSSM en suivant le modèle suivant :

nssm.exe install <service_name> "<chemin_vers_ps1>" "<argument1 argument2>"

Ce qui donne avec nos variables pour l'exécuter depuis la console PowerShell (exécutée en tant qu'admin) :

& $PathNSSM install $ServiceName $PathPowerShell $ServiceArguments

Vous devriez avoir un message indiquant que le service est installé ! Vous pouvez dans la foulée récupérer son statut :

& $PathNSSM status $ServiceName
Get-Service "Watch"

La seconde commande, Get-Service, est la commande classique avec PowerShell pour obtenir l'état d'un service 😉

Note : Si vous exécutez le service avec le compte "Système" ou un autre compte, vérifiez bien que le compte en question ait bien accès aux modules tiers que vous pourriez utiliser dans le script. Sinon, il faudra inclure l'installation du module dans votre script de service ou l'installer pour tous les utilisateurs.

Pour démarrer le service, c'est tout simple :

& $PathNSSM start $ServiceName

Ce qui est faisable également avec le cmdlet natif Start-Service mais pour le fun on le fait avec NSSM.

Remarque : Un service généré avec NSSM qui tourne exécutera un processus nssm.exe sur votre machine

A partir du moment où le service est lancé, vous pouvez tester qu'il fonctionne bien selon ce pour quoi il est prévu. Pour ma part, la surveillance avec Watch fonctionne à merveille !

Afin de peaufiner la configuration du service, on va définir une description, ce qui peut être aussi l'occasion d'indiquer le chemin vers le script PS1 qui est exécuté via ce service.

& $PathNSSM set $ServiceName description "Mon service Watch : $PathScript"

Enfin, il faut savoir :

  • Supprimer un service avec NSSM via la syntaxe suivante (sans demande de confirmation) :
nssm remove "<service_name>" confirm
  • Editer la configuration d'un service (syntaxe identique à celle utilisée pour modifier la description) :
nssm set "<service_name>" <paramètre> <valeur>

Ces deux commandes sont importantes notamment en phase de test où vous pourrez supprimer et recréer un service rapidement. Si la suppression échoue, vérifiez s'il y a un ou plusieurs processus nssm.exe qui tournent. Si c'est le cas, tuez-les.

Maintenant que vous êtes en mesure d'exécuter un script PowerShell via un service Windows, qu'allez-vous faire tourner?

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Florian BURNEL

Ingénieur système et réseau, cofondateur d'IT-Connect et Microsoft MVP "Cloud and Datacenter Management". Je souhaite partager mon expérience et mes découvertes au travers de mes articles. Généraliste avec une attirance particulière pour les solutions Microsoft et le scripting. Bonne lecture.

Nombre de posts de cet auteur : 5566.Voir tous les posts

One thought on “Comment exécuter un script PowerShell comme service ?

  • Bonjour,
    Super utile et très bien expliqué, bravo.

    Par contre j’ai un problème : j’ai suivi le tuto sur mon PC en Windows 10, ça marche nickel.
    Par contre, j’ai lancé exactement les mêmes commandes sur un PC qui tourne en Windows 11, et ça ne marche pas ! Le service se lance bien, il est running, mais le script powerhell qui est derrière ne fonctionne pas (il fonctionne quand je le lance à la main).

    Avez-vous une idée de ce qui se passe ?

    Merci !

    Répondre

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.