Guide des commandes PowerShell — Deploy-GLPIAgent.ps1
Chaque commande est présentée avec son rôle, sa syntaxe de principe et les pièges à éviter. L'ordre suit la logique du script.
Ce guide explique chaque commande dont tu as besoin, comme si tu n'avais jamais fait de PowerShell. Pour chacune : à quoi elle sert, comment sa syntaxe se lit mot par mot, comment la tester seule dans une console avant de la mettre dans le script, et les pièges classiques.
Les exemples de syntaxe sont génériques (c'est du PowerShell de base, documenté partout) : c'est à toi de les adapter et de les assembler pour construire ton script.
0. Les bases à connaître avant de commencer#
Cinq notions qui reviennent partout dans ce guide :
Une cmdlet : c'est le nom des commandes PowerShell. Elles suivent toujours le format Verbe-Nom : Get-Service (« obtenir - service »), New-Item (« créer - élément »), Remove-Item (« supprimer - élément »). Le verbe te dit ce que la commande fait.
Un paramètre : une option qu'on donne à une cmdlet, toujours précédée d'un tiret : Get-Service -Name glpi-agent. Ici -Name est le paramètre, et glpi-agent la valeur qu'on lui donne.
Une variable : une boîte pour ranger une valeur, toujours préfixée par $ :
$monDossier = "C:\Temp\GLPI"
Ensuite, écrire $monDossier n'importe où équivaut à écrire son contenu. Important : dans une chaîne entre guillemets doubles "...", les variables sont remplacées par leur valeur ; entre guillemets simples '...', non.
Un objet : en PowerShell, les commandes ne renvoient pas du texte mais des objets avec des propriétés. Exemple : Get-Service renvoie un objet service, qui a une propriété Status, une propriété Name, etc. On lit une propriété avec un point :
$service = Get-Service -Name glpi-agent
$service.Status
Pour découvrir toutes les propriétés d'un objet : $service | Get-Member.
Le pipeline | : la barre verticale envoie le résultat d'une commande à la commande suivante, comme une chaîne de montage :
commande1 | commande2 | commande3
Chaque commande travaille sur ce que la précédente lui a passé.
1. param(...) — recevoir les paramètres du script#
Rôle : permettre à celui qui lance le script de lui donner des informations (l'URL GLPI, le tag) sans modifier le code.
Le bloc param(...) se place tout en haut du fichier, avant toute autre instruction (seuls les commentaires peuvent le précéder). Comme c'est une syntaxe générique de PowerShell et pas la solution de l'exercice, voici le principe complet :
param(
[Parameter(Mandatory = $true)]
[string]$ServerUrl,
[string]$Tag,
[switch]$ForceReinstall
)
Ce qu'il faut comprendre, ligne par ligne :
[Parameter(Mandatory = $true)]rend le paramètre obligatoire. Si l'utilisateur lance le script sans-ServerUrl, PowerShell le lui demande interactivement au lieu de planter. L'attribut s'applique uniquement au paramètre qui le suit immédiatement.- Le type entre crochets (
[string],[switch]) force le type de la valeur reçue.[string]= une chaîne de caractères. Tagn'a pas d'attribut Mandatory : il est optionnel, et vaudra une chaîne vide si absent.[switch]est un type spécial pour les options oui/non : on ne lui passe pas de valeur. Présent sur la ligne de commande =$true, absent =$false. Dans le script, tu le testes avecif ($ForceReinstall) { ... }.- La virgule sépare chaque paramètre — c'est l'oubli classique qui fait planter le bloc.
À l'exécution, ça donne des appels comme :
.\Deploy-GLPIAgent.ps1 -ServerUrl "https://helpdesk.example.test/front/inventory.php" -Tag "TSSR-J7"
ou avec forçage :
.\Deploy-GLPIAgent.ps1 -ServerUrl "..." -Tag "TSSR-J7" -ForceReinstall
Ensuite, dans le corps du script, les variables $ServerUrl, $Tag et $ForceReinstall sont directement utilisables partout — pas besoin de les redéclarer.
Améliorations pour plus tard (quand la base fonctionne) : [ValidateNotNullOrEmpty()] sur ServerUrl pour refuser une chaîne vide, ou HelpMessage = "..." dans l'attribut Parameter. Le bloc simple suffit pour le minimum attendu.
2. Vérifier les droits administrateur#
Rôle : refuser de continuer si le script n'a pas les privilèges admin (sinon msiexec échouera plus loin, de façon moins claire).
Comprendre d'abord les trois notions#
Windows sépare trois choses :
- L'identité (identity) : QUI est connecté. Ton compte, son nom, son jeton de sécurité.
- Le principal (principal) : l'identité plus ses appartenances aux groupes. C'est l'objet capable de répondre à « cet utilisateur fait-il partie de tel groupe ? »
- Le rôle (role) : un groupe prédéfini de Windows (Administrators, Users, Guests...), listé dans l'énumération
WindowsBuiltInRole.
Le test = récupérer l'identité → l'envelopper dans un principal → demander au principal si l'identité appartient au rôle Administrator.
Piège UAC à connaître : être membre du groupe Administrateurs ne suffit pas. Avec l'UAC, un admin qui ouvre une console normale travaille avec un jeton filtré, sans les privilèges. Le test renverra $false tant que la console n'est pas ouverte via « Exécuter en tant qu'administrateur ». C'est exactement ce qu'on veut détecter.
Étape A — récupérer l'identité courante#
Syntaxe générique .NET/PowerShell :
$identite = [Security.Principal.WindowsIdentity]::GetCurrent()
Mot par mot :
- Les crochets autour du nom disent à PowerShell « ceci est un type (une classe .NET), pas une commande ».
::(deux-points doublés) : la syntaxe pour appeler une méthode statique — une méthode qu'on invoque directement sur la classe, sans créer d'objet avant.GetCurrent(): la méthode en question. Parenthèses vides = aucun argument. Elle renvoie un objet représentant l'utilisateur qui exécute le script.$identite = ...: on range le résultat pour l'étape suivante.
Mini-test : tape la ligne seule dans une console, puis $identite.Name. Tu dois voir ton MACHINE\utilisateur.
Étape B — construire le principal avec New-Object#
WindowsPrincipal n'a pas de méthode statique : il faut fabriquer un objet, et sa recette de fabrication (son constructeur) exige une identité. Forme générale de New-Object :
$objet = New-Object NomComplet.De.LaClasse($cequonluidonne)
- La classe à utiliser ici :
Security.Principal.WindowsPrincipal - L'argument attendu entre parenthèses : ta variable de l'étape A.
- Range le résultat dans une variable, par exemple
$principal.
À toi d'assembler cette ligne.
Étape C — poser la question avec .IsInRole()#
Le principal possède une méthode d'instance .IsInRole() (« est dans le rôle ? »). Contrairement à l'étape A, elle s'appelle avec un simple point sur la variable :
$variable.NomDeLaMethode(argument)
- L'argument à mettre entre parenthèses est le rôle à vérifier. Le rôle Administrateur est une valeur d'énumération (une liste fermée de valeurs nommées), et on y accède avec la même syntaxe
:::
[Security.Principal.WindowsBuiltInRole]::Administrator
Ici le :: désigne une valeur de la liste, pas une méthode. - Le retour est un booléen : $true si les privilèges admin sont actifs, $false sinon. Range-le dans une variable du genre $estAdmin.
Étape D — réagir si le test échoue#
Un booléen se teste directement dans un if, sans le comparer à quoi que ce soit :
if (-not $estAdmin) {
# erreur claire + sortie (voir section 12)
}
-notinverse la condition : « si PAS admin, alors... ».- Dans le bloc :
Write-Erroravec un message qui dit quoi faire (relancer PowerShell en tant qu'administrateur), puisexit 1.
Ce test doit être la première action après le bloc param.
Validation : console normale → refus avec ton message. Console « Exécuter en tant qu'administrateur » → le script continue. Les deux comportements bons = étape validée.
3. Join-Path — construire un chemin proprement#
Rôle : coller deux morceaux de chemin sans se soucier des \.
Syntaxe générique :
$chemin = Join-Path <cheminParent> <nomEnfant>
Ce qu'il faut comprendre :
- Le premier argument est le dossier parent, le second ce qu'on ajoute dedans.
- La cmdlet gère elle-même le séparateur
\: pas de risque de double\\ou de\oublié comme avec une concaténation$a + "\" + $b. - Pour le dossier temporaire, le parent tout trouvé est la variable d'environnement
$env:TEMP: c'est le dossier temporaire de Windows, déjà connu du système. Les variables$env:...donnent accès aux variables d'environnement Windows ($env:TEMP,$env:COMPUTERNAME, etc.).
Mini-test : Join-Path $env:TEMP "Essai" dans une console → affiche un chemin du genre C:\Users\toi\AppData\Local\Temp\Essai. Rien n'est créé : Join-Path fabrique juste la chaîne de texte du chemin.
4. Test-Path — vérifier qu'un chemin existe#
Rôle : savoir si un dossier ou fichier existe déjà, avant d'agir.
Syntaxe générique :
Test-Path <chemin>
- Renvoie un booléen :
$truesi le chemin existe,$falsesinon. - Comme c'est un booléen, ça se met directement dans un
if:
if (Test-Path $monChemin) { ... }
if (-not (Test-Path $monChemin)) { ... }
Note les parenthèses supplémentaires autour de Test-Path ... quand on combine avec -not : sans elles, PowerShell croit que -not est un argument de Test-Path.
Mini-test : Test-Path C:\Windows → True. Test-Path C:\NExistePas → False.
5. New-Item — créer le dossier temporaire#
Rôle : créer le dossier de travail où le MSI sera téléchargé.
Syntaxe générique :
New-Item -ItemType Directory -Path <chemin> -Force | Out-Null
Mot par mot :
-ItemType Directory: on précise qu'on crée un dossier (la même cmdlet sait aussi créer des fichiers, d'où la précision).-Path: où le créer — utilise la variable construite avecJoin-Path.-Force: ne pas planter si le dossier existe déjà.| Out-Null:New-Itemrenvoie un objet décrivant le dossier créé, et PowerShell l'afficherait à l'écran.Out-Nulljette cet affichage à la poubelle pour garder une sortie propre.
Mini-test : crée un dossier d'essai dans $env:TEMP, vérifie avec Test-Path, puis supprime-le (section 13).
6. Invoke-WebRequest — télécharger le MSI#
Rôle : télécharger un fichier depuis une URL vers le disque.
Syntaxe générique :
Invoke-WebRequest -Uri <URL> -OutFile <cheminDestination> -UseBasicParsing -ErrorAction Stop
Mot par mot :
-Uri: l'adresse à télécharger (l'URL du MSI x64 — celle trouvée via l'API GitHub dans la version bonus, ou l'URL de la release fournie sinon).-OutFile: le chemin complet du fichier de destination, dans ton dossier temporaire (pas dans Downloads — c'est une contrainte de l'énoncé). Construis-le avecJoin-Path: ton dossier temp + le nom du fichier MSI.-UseBasicParsing: option de compatibilité (évite une dépendance à Internet Explorer sur les vieux PowerShell). Ne coûte rien, mets-la.-ErrorAction Stop: voir section 11 — transforme un échec de téléchargement en erreur bloquante, pour que tontry/catchla voie.
Pièges :
- Sans
-OutFile, la cmdlet ne sauvegarde rien sur le disque : elle renvoie la réponse en mémoire. - Un téléchargement qui « réussit » mais renvoie une page d'erreur HTML au lieu d'un MSI, ça arrive : c'est justement le contrôle SHA256 (section suivante) qui te protège de ça.
Mini-test : télécharge n'importe quel petit fichier public vers $env:TEMP, puis vérifie son existence avec Test-Path.
7. Get-FileHash — contrôler le SHA256#
Rôle : calculer l'empreinte du fichier téléchargé et la comparer à l'empreinte officielle, pour garantir que le MSI est intact et authentique.
Ce qu'est un hash, en deux mots#
Un hash SHA256 est une empreinte digitale du fichier : une longue chaîne hexadécimale calculée à partir de son contenu. Si un seul octet du fichier change, l'empreinte change du tout au tout. Comparer ton empreinte calculée à l'empreinte publiée par l'éditeur prouve que le fichier est exactement celui attendu.
Calculer le hash#
Syntaxe générique :
$resultat = Get-FileHash <cheminDuFichier> -Algorithm SHA256
-Algorithm SHA256: l'algorithme demandé par l'énoncé.- Attention :
$resultatn'est PAS le hash. C'est un objet avec plusieurs propriétés (Algorithm,Hash,Path). Le hash lui-même est dans la propriété.Hash:
$resultat.Hash
C'est cette propriété (une chaîne en MAJUSCULES) qu'il faut comparer.
Comparer avec le hash attendu#
L'opérateur de comparaison d'égalité en PowerShell est -eq (pas == comme dans d'autres langages) :
if ($valeurA -eq $valeurB) { ... }
- Sur des chaînes,
-eqest insensible à la casse par défaut : pratique, car les hash publiés sur GitHub sont souvent en minuscules et ceux deGet-FileHashen majuscules. La comparaison directe fonctionne. - Le hash attendu vient soit du champ
digestde l'asset GitHub (bonus, voir section 15 — attention, il peut être préfixé parsha256:, à retirer avant de comparer), soit du fichier.sha256publié avec la release. - Si les deux hash diffèrent : erreur claire et ARRÊT du script, sans installer. C'est tout l'intérêt du contrôle.
Mini-test : calcule le hash d'un fichier quelconque deux fois → même résultat. Modifie une lettre dans un fichier texte, recalcule → résultat totalement différent.
8. Start-Process + msiexec — installer en silencieux#
Rôle : lancer l'installateur Windows (msiexec.exe) sans interface, avec les options GLPI, et savoir si l'installation a réussi.
Pourquoi Start-Process et pas juste taper la commande ?#
On pourrait écrire msiexec /i ... directement, mais PowerShell rendrait la main immédiatement, sans attendre la fin de l'installation, et sans te donner le résultat. Start-Process règle les deux problèmes avec -Wait et -PassThru.
Syntaxe générique :
$processus = Start-Process -FilePath <programme> -ArgumentList <tableauDArguments> -Wait -PassThru
Mot par mot :
-FilePath: le programme à lancer, ici"msiexec.exe".-ArgumentList: les arguments à lui passer, sous forme de tableau de chaînes séparées par des virgules :
-ArgumentList "/i", $cheminMsi, "/quiet", "/norestart", "OPTION1=valeur", "OPTION2=valeur"
-Wait: attendre que msiexec ait terminé avant de continuer le script.-PassThru: renvoyer un objet représentant le processus. Sans lui,Start-Processne renvoie rien.$processus.ExitCode: le code de sortie de msiexec, lisible après coup grâce à-PassThru+-Wait.
Les arguments msiexec à connaître#
/isuivi du chemin du MSI : « installer ce paquet »./quiet: aucune interface, aucune question./norestart: ne pas redémarrer le poste tout seul.- Les options GLPI Agent au format
OPTION=valeur— sans espace autour du=(contrainte de l'énoncé). Celles qui t'intéressent :SERVER=(avec ta variable$ServerUrl),TAG=(avec$Tag), et l'option qui déclenche un inventaire immédiat — chercheRUNNOWdans la doc officielle « Windows installer » de GLPI Agent. Le mode service Windows est le comportement par défaut de l'installateur.
Interpréter le code de sortie#
Ton script doit tester ExitCode et considérer 0 et 3010 comme des succès.
Pièges :
- Si le chemin du MSI contient des espaces, entoure-le de guillemets supplémentaires dans l'argument (guillemets dans la chaîne).
- Grâce aux guillemets doubles,
"SERVER=$ServerUrl"insère bien la valeur de la variable. Avec des guillemets simples, non. - La piste 5 de l'énoncé propose une variante : préparer la ligne complète puis l'exécuter via
cmd.exe /c msiexec.exe .... Les deux approches sont acceptables ;Start-Processte donne le code de sortie plus proprement.
9. Get-Service — vérifier l'état du service#
Rôle : contrôler qu'après installation, le service glpi-agent existe et tourne.
Syntaxe générique :
$service = Get-Service -Name <nomDuService>
- Le nom du service à vérifier ici :
glpi-agent. - Le résultat est un objet avec notamment la propriété
.Status: valeurs possiblesRunning(démarré),Stopped(arrêté), etc. - Comportement en cas d'absence : si le service n'existe pas, la cmdlet lève une erreur. Deux stratégies au choix :
-ErrorAction Stop→ l'absence part dans toncatch(service manquant = installation ratée = échec clair) ;-ErrorAction SilentlyContinue→ la variable reste vide, et tu testesif ($null -eq $service) { ... }pour gérer le cas toi-même.
Pour l'affichage final demandé par l'énoncé, montrer .Status (et éventuellement .Name) suffit.
Mini-test : Get-Service -Name Spooler (le spouleur d'impression, présent sur tout Windows) → observe l'objet renvoyé et sa propriété Status.
10. Start-Service — démarrer le service si besoin#
Rôle : si le service est installé mais arrêté, le démarrer.
Syntaxe générique :
Start-Service -Name <nomDuService>
- À placer dans un
if: seulement si.Statusn'est pasRunning. - La comparaison « différent de » en PowerShell :
-ne(not equal), le cousin de-eq. - Après un
Start-Service, relis l'état avecGet-Servicepour l'afficher dans ton résumé.
11. try / catch / finally + -ErrorAction — gérer les erreurs#
Rôle : intercepter les échecs (téléchargement, service absent...) pour afficher un message clair au lieu d'un pavé rouge illisible, et garantir le nettoyage final.
La structure#
try {
# les étapes qui peuvent échouer
}
catch {
# ce qu'on fait si une erreur bloquante survient dans le try
}
finally {
# exécuté DANS TOUS LES CAS, succès ou échec
}
Ce qu'il faut comprendre :
- Dès qu'une erreur bloquante survient dans le
try, PowerShell saute immédiatement dans lecatch(le reste dutryn'est pas exécuté). - Dans le
catch, la variable automatique$_contient l'erreur.$_.Exception.Messageen donne le message lisible, à intégrer dans ton propre message d'erreur. - Le
finallyest optionnel mais précieux : c'est l'endroit idéal pour le nettoyage du dossier temporaire (section 13), car il s'exécute même si tout a explosé avant.
Le piège n°1 du débutant : -ErrorAction Stop#
Beaucoup de cmdlets lèvent par défaut des erreurs non bloquantes : elles affichent du rouge mais le script continue, et le catch ne se déclenche pas. Pour forcer une cmdlet à produire une erreur bloquante (donc « catchable ») :
UneCmdlet -SesParametres -ErrorAction Stop
Mets -ErrorAction Stop sur toutes les étapes critiques : téléchargement, calcul de hash, vérification du service. Sans ça, ton try/catch semble ne « pas marcher ».
Mini-test : dans une console, essaie Get-Service -Name nexistepas seul, puis la même chose dans un try/catch sans -ErrorAction Stop (le catch ne se déclenche pas), puis avec (le catch se déclenche). La différence saute aux yeux.
12. Write-Host, Write-Error, exit — afficher et signaler#
Rôle : informer l'utilisateur de l'avancement, et signaler un échec de façon exploitable.
Write-Host — messages d'avancement#
Write-Host "Etape X : ce que je suis en train de faire..."
Write-Host "OK" -ForegroundColor Green
Write-Host "ECHEC" -ForegroundColor Red
- Affiche du texte à l'écran, c'est tout.
-ForegroundColorcolore le texte : vert pour les succès, rouge pour les échecs — très lisible pour ton compte rendu.- Bonne pratique : un message avant chaque grande étape, et un message de résultat après. C'est ce qui rend le script « relisible » et son exécution compréhensible.
Write-Error — signaler une erreur#
Write-Error "Description claire du probleme et quoi faire"
- Affiche le message sur le flux d'erreur (en rouge), le canal prévu pour ça — contrairement à un simple
Write-Hostrouge. - À utiliser dans tes
catchet tes tests qui échouent (hash invalide, pas admin...).
exit — sortir avec un code#
exit 1
- Termine le script immédiatement, avec un code de sortie :
0= tout s'est bien passé (c'est le code par défaut si le script va au bout), toute autre valeur = échec. - Ce code est le même mécanisme que l'
ExitCodede msiexec : il permet à un autre outil (ou au formateur) de savoir si ton script a réussi sans lire les messages. - Le duo classique en cas de pépin :
Write-Error "..."puisexit 1.
13. Remove-Item — nettoyer à la fin#
Rôle : supprimer le dossier temporaire et le MSI téléchargé une fois l'installation terminée.
Syntaxe générique :
Remove-Item -Path <chemin> -Recurse -Force
-Recurse: supprime aussi tout le contenu du dossier (sans lui, un dossier non vide fait échouer la suppression, avec une question interactive).-Force: supprime aussi les fichiers cachés ou en lecture seule.- Où le placer : dans le bloc
finally(section 11), pour que le nettoyage ait lieu même si le script a échoué en route. - Prudence de débutant : vérifie que la variable de chemin n'est pas vide avant de supprimer (un
Test-Pathdans uniffait l'affaire).Remove-Item -Recurse -Forcesur un mauvais chemin ne pardonne pas.
PARTIE BONUS
À n'attaquer que quand le minimum fonctionne de bout en bout.
14. Invoke-RestMethod — interroger l'API GitHub#
Rôle : demander à GitHub la liste des releases GLPI Agent pour trouver automatiquement la dernière version et son MSI x64.
API et JSON, en deux mots#
Une API web est une URL qui, au lieu de renvoyer une page à regarder, renvoie des données structurées au format JSON (du texte organisé en champs et listes). L'URL à utiliser est donnée dans la piste 3 de l'énoncé.
Syntaxe générique :
$reponse = Invoke-RestMethod -Uri <urlDeLApi>
Ce qu'il faut comprendre :
- Cousine d'
Invoke-WebRequest, mais elle convertit automatiquement le JSON en objets PowerShell. Pas de texte à découper : tu obtiens directement des objets avec des propriétés. - Ici,
$reponseest un tableau de releases. Chaque release a notamment : .tag_name: le nom de version (ex. un tag contenant « 1.18 ») ;.prerelease:$truesi c'est une préversion (à écarter) ;.draft:$truesi c'est un brouillon (à écarter) ;.assets: la liste des fichiers publiés avec la release. Chaque asset a un.name(nom du fichier), une.browser_download_url(l'URL de téléchargement à donner ensuite àInvoke-WebRequest), et éventuellement un.digest(le hash, voir section 7).
Mini-test : appelle l'API dans une console, puis explore : $reponse.Count (combien de releases ?), $reponse[0].tag_name (la plus récente — les crochets [0] prennent le premier élément d'un tableau), $reponse[0].assets.name (les fichiers de cette release).
15. Where-Object — filtrer les releases et les assets#
Rôle : garder uniquement les releases stables, puis trouver l'asset GLPI-Agent-*-x64.msi.
Syntaxe générique :
$resultat = $collection | Where-Object { <condition sur $_> }
Ce qu'il faut comprendre :
Where-Objectreçoit une collection par le pipeline|et ne laisse passer que les éléments pour lesquels la condition entre{ }est vraie.- Dans la condition,
$_désigne l'élément en cours d'examen (chaque release, ou chaque asset, tour à tour). - Opérateurs utiles dans la condition :
-not: inversion. Pour garder les stables :-not $_.prerelease;-and: combiner deux conditions (pas prerelease et pas draft) ;-like: comparaison avec joker*(le*remplace n'importe quoi). Pour l'asset : condition sur$_.nameavec le motif"GLPI-Agent-*-x64.msi".
Tu auras donc deux filtrages : un sur $reponse (les releases), puis un sur la propriété .assets de la release retenue (les fichiers).
Mini-test : Get-Service | Where-Object { $_.Status -eq "Running" } → uniquement les services démarrés. Le principe est identique.
16. Select-Object -First 1 — garder la plus récente#
Rôle : après filtrage, ne retenir que la première release de la liste.
Syntaxe générique :
$premier = $collection | Select-Object -First 1
- L'API GitHub renvoie les releases triées de la plus récente à la plus ancienne : le premier élément après filtrage est donc la dernière version stable.
- S'enchaîne naturellement après
Where-Objectdans le même pipeline : filtre, puis prends le premier.
17. Get-ItemProperty sur le registre — version installée#
Rôle : détecter si GLPI Agent est déjà présent sur le poste, et en quelle version.
Le registre, en deux mots#
Le registre Windows est la base de configuration du système. PowerShell y navigue comme dans un disque : HKLM: (HKEY_LOCAL_MACHINE, la config machine) s'utilise comme C:. Chaque programme installé laisse une clé de désinstallation contenant son nom et sa version.
Syntaxe générique :
$programmes = Get-ItemProperty -Path <cheminRegistre>
Ce qu'il faut comprendre :
- Le chemin des programmes installés :
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*— le*final signifie « toutes les sous-clés », donc tous les programmes. - Par acquit de conscience, il existe une seconde branche pour les programmes 32 bits : même chemin avec
WOW6432Nodeintercalé aprèsSOFTWARE. - Chaque objet renvoyé a (entre autres) :
.DisplayName: le nom du programme tel qu'affiché ;.DisplayVersion: sa version, en chaîne de caractères.- Pour isoler GLPI Agent : un
Where-Object(section 15) avec une condition-likesur.DisplayNameet le motif"GLPI Agent*". - Si le filtrage ne renvoie rien : l'agent n'est pas installé — c'est une information utile, pas une erreur (le script doit alors installer).
Mini-test : liste tout avec ce chemin, affiche les DisplayName, et retrouve à l'œil des programmes que tu connais.
18. Le cast [version] — comparer deux versions#
Rôle : comparer correctement la version locale et la version en ligne pour décider s'il faut installer.
Pourquoi ne pas comparer les chaînes directement#
En comparaison de chaînes, "1.9" est supérieur à "1.18" (comparaison caractère par caractère : « 9 » > « 1 »). C'est faux au sens des versions. Le type [version] de .NET compare nombre par nombre : 1.18 > 1.9, comme attendu.
Syntaxe générique du cast (conversion de type) :
[version]$maChaine
- Placer
[version]devant une chaîne la convertit en objet version comparable. - Les opérateurs de comparaison PowerShell :
-lt(less than, inférieur),-gt(greater than, supérieur),-eq(égal),-le/-ge(inférieur ou égal / supérieur ou égal). Exemple de principe :
if ([version]$versionLocale -lt [version]$versionEnLigne) { ... }
Pièges :
- La chaîne doit être purement numérique à points (« 1.18 », « 1.18.0 »). Le
.tag_nameGitHub peut contenir un préfixe non numérique : nettoie la chaîne avant le cast (regarde du côté de la méthode.TrimStart()ou de l'opérateur-replace). - Prévois le cas « rien d'installé » (section 17) : pas de version locale à comparer → on installe, tout simplement.
- C'est ici que se branche le paramètre
ForceReinstall: même à jour, si le switch est présent, on installe quand même.
Mini-test : dans une console, compare "1.9" -lt "1.18" (résultat surprenant) puis [version]"1.9" -lt [version]"1.18" (résultat correct). Tu verras immédiatement pourquoi le cast est indispensable.
Ordre d'assemblage du script
param— paramètres (section 1)- Test admin (section 2)
- Variables importantes visibles en début de script (chemins, noms...)
- Dossier temporaire (sections 3, 4, 5)
- (Bonus) API GitHub → release stable → asset x64 (sections 14, 15, 16)
- (Bonus) Version locale + comparaison + ForceReinstall (sections 17, 18)
- Téléchargement (section 6)
- Contrôle SHA256 — arrêt si différent (section 7)
- Installation msiexec + code de sortie (section 8)
- Vérification / démarrage du service (sections 9, 10)
- Résumé final pour le compte rendu (section 12)
- Nettoyage dans le
finally(sections 11, 13)
Le tout enveloppé dans try / catch / finally, avec -ErrorAction Stop sur les étapes critiques.
Méthode de travail conseillée
- Teste chaque commande seule dans une console avec les mini-tests de ce guide, avant de l'écrire dans le script.
- Construis le script étape par étape : fais fonctionner le test admin seul, puis ajoute le dossier temporaire, puis le téléchargement, etc. Relance le script à chaque ajout.
- Garde les bonus pour la fin, un par un, sans casser ce qui marche.
- Note au fur et à mesure les infos demandées pour le compte rendu (version détectée, URL du MSI, résultat du hash, code de sortie, état du service).
Ces articles devraient vous plaire
Windows
Installation et configuration de GLPI agent sur un poste Windows
L'on va installer le GLPI agent sur windows en une seule ligne de commande
Outils Linux
TABBY - Le terminal moderne pour votre Linux
Si comme moi vous êtes passé de Windows à Linux, et vous aviez l'habitude de travailler sur le nouveau...
Virtualisation
Déploiement de 2 machines win11 depuis master vmware
Mettre en service 2 VM Windows via clone depuis un master sur VMware, dans le cadre du projet SupportLab.
Commentaires (0)
Aucun commentaire pour l'instant. Ouvrez le bal.
Laisser un commentaire