Objectifs d'apprentissage
À la fin de ce cours, l'apprenant peut :
- lancer
pwshsur macOS et dire ce qui le distingue de Windows PowerShell 5.1 ; - lire et écrire une commande au format
Verb-Nounet la découvrir avecGet-Command,Get-HelpetGet-Member; - expliquer que le tube transporte des objets et non du texte, et en tirer parti ;
- filtrer, sélectionner, trier et transformer avec
Where-Object,Select-Object,Sort-ObjectetForEach-Object; - choisir un format d'affichage (
Format-Table,Format-List) sans casser le pipeline ; - utiliser variables, types, tableaux et tables de hachage ;
- écrire une fonction avancée avec
[CmdletBinding()], des paramètres typés et de la validation ; - gérer les erreurs avec
-ErrorAction,try/catch/finally; - lire et écrire des fichiers, du JSON et du CSV ;
- rendre un script prudent avec
-WhatIf,-ConfirmetSupportsShouldProcess; - dire ce qu'est la politique d'exécution et pourquoi elle n'est pas une frontière de sécurité ;
- évaluer un module de la PowerShell Gallery avant de l'installer, et traiter les secrets sans les écrire en clair ;
- adopter l'habitude « lecture seule d'abord ».
Prérequis
- Savoir ouvrir Terminal et lire une commande avant de la valider (cours « Terminal macOS »).
- Notions de scripts shell (cours « Scripting shell et Python ») : utiles pour comparer, pas obligatoires.
- PowerShell 7 installé sur le Mac de Stéphane : non vérifié. Ce cours n'installe rien. La seule référence d'installation est la page officielle à lire : <https://learn.microsoft.com/en-us/powershell/scripting/install/install-powershell-on-macos (s’ouvre dans un nouvel onglet)> (le paquet macOS y est présenté comme signé et notarisé par Microsoft à partir des versions de mai 2026).
- Un dossier de test jetable. Aucun exercice ne demande de droits administrateur.
Parcours et chapitres
1. PowerShell 7 sur macOS et différences avec Windows PowerShell 5.1
PowerShell est un shell et un langage de script. Selon la page « Differences between Windows PowerShell 5.1 and PowerShell 7.x » :
| Point | Windows PowerShell 5.1 | PowerShell 7.x (pwsh) |
|---|---|---|
| Plateformes | Windows | Windows, macOS, Linux |
| Plateforme logicielle | .NET Framework 4.5 | .NET moderne (7.6 : .NET 10, LTS) |
| Exécutable | powershell.exe | pwsh (pwsh-preview pour une préversion) |
| Modules et applets de commande | ensemble Windows complet | certains retirés (ISE, PSWorkflow, PSScheduledJob, snap-ins, plusieurs cmdlets Windows) |
| Compatibilité | peut charger de nombreux modules 5.1 ; fonction « Windows PowerShell Compatibility » pour les autres (Windows) |
La page indique que les différences de langage sont peu nombreuses ; les plus visibles sont la disponibilité et le comportement des cmdlets selon la plateforme, et les changements dus à .NET. Sur macOS, les cmdlets propres à Windows (registre, services Windows, WMI, etc.) ne sont pas disponibles : la liste exacte par cmdlet est non vérifiée.
À retenir : un script écrit pour Windows PowerShell 5.1 peut ne pas fonctionner sous pwsh sur macOS, à cause de cmdlets absentes, de chemins (C:\ contre /), de la casse des noms de fichiers sous APFS (selon la configuration du volume : non vérifié) et de changements de méthodes .NET. Tester sous pwsh avant de généraliser.
D'après la page d'installation, après l'installation du paquet on lance pwsh depuis Terminal ; le profil utilisateur est lu dans ~/.config/powershell/profile.ps1, les modules utilisateur dans ~/.local/share/powershell/Modules, et PowerShell respecte la spécification XDG sur macOS. Les mises à jour se font en installant le nouveau paquet.
pwsh$PSVersionTable.PSVersion$PSVersionTable.OSexitBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : Terminal macOS,
pwshinstallé (non vérifié). Les lignes aprèspwshse tapent dans la session PowerShell ;$PSVersionTableest une variable automatique décrite dans la documentation PowerShell (page non relue, voir « Points non vérifiés »). - Droits : utilisateur normal.
- Effet : ouvre une session PowerShell, affiche la version et le système, puis ferme la session. Aucune modification.
- Vérification : la version affichée est celle de
pwsh(et non celle de la documentation) ; c'est le chiffre à noter pour compléter ce cours. - Retour arrière : sans objet (
exitferme la session).
Pour exécuter une seule commande sans session interactive : pwsh -NoProfile -Command "Get-Date" (option -NoProfile et -Command : usage courant, non vérifié sur la page de ligne de commande, non lue).
2. Cmdlets et convention Verb-Noun
Une cmdlet (« commandlet ») est une commande de PowerShell nommée Verbe-Nom : un verbe d'une liste approuvée, un nom au singulier, par exemple Get-Process, Get-ChildItem, Set-Location. La cohérence fait l'intérêt du langage : tous les Get-* lisent, tous les Remove-* suppriment. Les paramètres commencent par - et sont nommés (-Path, -Name). PowerShell ne distingue pas les majuscules des minuscules pour les cmdlets et leurs paramètres.
| Verbe | Sens habituel | Effet |
|---|---|---|
Get | lire | aucun |
Select, Where, Sort, Measure, Format, Test | filtrer, trier, mesurer, tester | aucun sur le système |
Set, New, Add, Rename, Move, Copy | modifier, créer | oui |
Remove, Stop, Clear, Restart | supprimer, arrêter | oui, parfois irréversible |
Invoke | exécuter | selon la cible |
Cette table décrit l'usage courant ; la liste officielle des verbes approuvés (Get-Verb) n'a pas été relue : non vérifié.
Attention : le verbe donne une indication, pas une garantie. Un Get-* d'un module tiers peut avoir des effets. Lire l'aide avant d'utiliser une cmdlet inconnue.
Des alias existent (ls, dir, cat, ps, gci, %, ?). Utiles en interactif, à éviter dans un script : sur macOS et Linux, PowerShell 7 ne redéfinit pas certains alias pour laisser les commandes natives (ls, cat…) passer (comportement non vérifié dans les pages lues). Dans un script, écrire le nom complet.
3. Découvrir : Get-Command, Get-Help, Get-Member
Trois cmdlets suffisent pour explorer, sans rien modifier :
Get-Command -Verb Get -Noun Process*Get-Help Get-Process -ExamplesGet-Process | Get-Member -MemberType PropertyBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh; PowerShell 7.x (version non vérifiée). Le contenu complet de l'aide peut demanderUpdate-Help: voir ci-dessous. - Droits : utilisateur normal.
- Effet : la première liste les commandes qui lisent des processus, la deuxième affiche des exemples d'utilisation de
Get-Process, la troisième liste les propriétés des objets processus. Aucune modification. - Vérification : chaque commande affiche du texte ; si
Get-Helpne montre que la syntaxe, l'aide complète n'est pas installée sur ce poste. - Retour arrière : sans objet.
Get-Command: trouve des commandes par nom, verbe, nom commun ou module (-Module).Get-Help <cmdlet>: syntaxe et description ;-Examples,-Detailed,-Full,-Online(ouvre la page web). Les pages « about_* » (Get-Help about_Pipelines) expliquent les concepts.Get-Member: liste les propriétés et méthodes d'un objet reçu par le tube ; c'est l'outil central pour comprendre ce qu'on manipule.Update-Helptélécharge l'aide complète (accès réseau et écriture dans les dossiers d'aide, droits potentiellement élevés pour les modules du système : non vérifié). Ne pas le lancer sans l'avoir lu.
Astuce : quand une sortie surprend, ajoutez | Get-Member : vous voyez le type de l'objet et les noms exacts des propriétés à filtrer.
4. Le pipeline d'objets : la différence majeure
Dans un shell classique (bash, zsh), le tube | transporte du texte : on découpe des colonnes avec awk, cut, grep. Dans PowerShell, une cmdlet envoie des objets .NET, avec des propriétés nommées et typées ; l'étape suivante lit ces propriétés directement. D'après la documentation (about_Pipelines, page à relire), le tube passe les objets un à un à la commande suivante.
Comparaison :
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, Id, CPUBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh; la propriétéCPUdes processus et son unité dépendent de la plateforme (non vérifié sur macOS). - Droits : utilisateur normal ; certains processus d'autres utilisateurs peuvent exposer moins de propriétés.
- Effet : lit les processus, les trie par temps processeur décroissant, garde cinq objets et trois propriétés, puis les affiche. Aucune modification du système.
- Vérification : cinq lignes, trois colonnes (
Name,Id,CPU) ; essayer| Get-MemberaprèsGet-Processpour voir toutes les propriétés. - Retour arrière : sans objet.
L'équivalent shell exigerait de découper une colonne de texte par sa position : fragile. Ici, on trie sur une propriété.
À retenir : réfléchir « objet » : quelle propriété, de quel type ? Ne pas convertir en texte (Out-String, Format-*) avant d'avoir fini de filtrer. Les cmdlets Format-* produisent des objets de mise en forme destinés à l'affichage ; les placer en dernier (comportement décrit dans la documentation de mise en forme, non relu : à confirmer).
5. Filtrer, sélectionner, trier, transformer
| Cmdlet | Rôle | Exemple |
|---|---|---|
Where-Object | garder les objets qui répondent à une condition | Where-Object { $_.CPU -gt 10 } ou Where-Object CPU -gt 10 |
Select-Object | choisir des propriétés ou le début / la fin de la liste | Select-Object Name, Id ; -First 3 ; -Last 3 |
Sort-Object | trier sur une ou plusieurs propriétés | Sort-Object Length -Descending |
ForEach-Object | appliquer un bloc à chaque objet | ForEach-Object { $_.Name.ToUpper() } |
Measure-Object | compter, additionner | Measure-Object -Property Length -Sum |
Group-Object | regrouper par propriété | Group-Object Extension |
$_ (ou $PSItem) désigne l'objet courant dans un bloc de script. Opérateurs de comparaison : -eq, -ne, -gt, -lt, -ge, -le, -like (jokers), -match (expression régulière), -in, -contains, -and, -or, -not. Ils ne sont pas des symboles (==, >) : attention, > est la redirection de fichier, qui écrit un fichier.
Get-ChildItem -File | Where-Object { $_.Length -gt 1KB } | Sort-Object Length -Descending | Select-Object Name, LengthBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, dossier de test contenant quelques fichiers synthétiques ;KBest un suffixe numérique du langage (1KB = 1024), non vérifié dans une page lue. - Droits : lecture du dossier courant.
- Effet : liste les fichiers de plus d'un kilo-octet, du plus gros au plus petit, avec nom et taille. Aucune modification.
- Vérification : la colonne
Lengthest décroissante et aucune valeur n'est inférieure à 1024 ; en cas de résultat vide, le dossier ne contient pas de fichier assez gros. - Retour arrière : sans objet.
Astuce : filtrer le plus tôt possible. Get-ChildItem -Filter *.txt (le filtre est appliqué par la source) est généralement plus efficace que Get-ChildItem | Where-Object Name -like '*.txt' (comportement courant, non vérifié).
6. Formater et exporter
Format-Table(ft),Format-List(fl) : mise en forme d'affichage pour l'œil, à placer en dernier.Out-String: transforme en texte (pour un message), à utiliser rarement.Out-File,Export-Csv,ConvertTo-Json,Out-GridView(graphique, Windows) : pour sortir des données ; vérifier leur disponibilité sous macOS.
Get-Process | Select-Object -First 3 Name, Id | Format-Table -AutoSizeGet-Process | Select-Object -First 3 Name, Id | Format-ListBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh. - Droits : utilisateur normal.
- Effet : affiche trois processus en tableau, puis en liste (une propriété par ligne). Aucune modification.
- Vérification : même contenu, deux présentations.
- Retour arrière : sans objet.
Attention : ne mettez jamais Format-Table avant Export-Csv ou ConvertTo-Json : vous exporteriez des objets de mise en forme et non vos données. Filtrez, puis exportez, ou formatez pour l'écran seulement.
7. Variables, types, tableaux et tables de hachage
Les variables commencent par $. Le typage est dynamique mais on peut contraindre avec un type entre crochets.
$nom = "demo"[int]$compte = 3$liste = @("a", "b", "c")$config = @{ Hote = "exemple.test"; Port = 8080 }$liste.Count$config.Port$nom.GetType().NameBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh; chaînes et valeurs synthétiques (example.test/exemple.test: nom réservé aux exemples). - Droits : utilisateur normal.
- Effet : crée des variables en mémoire de la session (aucun fichier).
@( )crée un tableau,@{ }une table de hachage (clé = valeur) ;.Count,.Portet.GetType().Namelisent des valeurs. - Vérification :
3,8080etStrings'affichent. - Retour arrière :
Remove-Variable nom, compte, liste, configou fermer la session. La syntaxe@(),@{}et le typage sont la connaissance usuelle du langage : non relue sur la page « about_Arrays » / « about_Hash_Tables ».
Points de vigilance :
- guillemets doubles
"...": expansion des variables ("Bonjour $nom") ; guillemets simples'...': texte littéral. Pour un texte non fiable, préférer les guillemets simples. - Une table de hachage
[ordered]@{}conserve l'ordre ;[pscustomobject]@{ Nom = 'a'; Taille = 1 }crée un objet à propriétés nommées. - Splatting : passer une table de hachage comme paramètres avec
@params(rappelé par la page ShouldProcess lue :Remove-Item @RemoveSplat). $null,$true,$falsesont les valeurs spéciales. Un résultat à un seul élément n'est pas un tableau : utiliser@(...)pour forcer un tableau.
8. Fonctions et paramètres
Une fonction avancée se déclare avec [CmdletBinding()] : elle gagne alors les paramètres communs (-Verbose, -ErrorAction, -WhatIf si demandé…). La validation des paramètres se fait par attributs. Exemple en lecture seule :
function Get-FichierVolumineux { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })] [string]$Dossier, [ValidateRange(1, 1048576)] [int]$TailleMinKo = 1024 ) Get-ChildItem -LiteralPath $Dossier -File | Where-Object { $_.Length -ge ($TailleMinKo * 1KB) } | Select-Object Name, Length}Get-FichierVolumineux -Dossier . -TailleMinKo 1Bloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh; PowerShell 7.x.[Parameter(Mandatory)],[ValidateScript],[ValidateRange]et-LiteralPath: usages décrits dans la documentation (pages « about_Functions_Advanced_Parameters » non relues ici : non vérifié). - Droits : lecture du dossier passé en argument.
- Effet : déclare la fonction dans la session (mémoire) puis liste les fichiers d'au moins
TailleMinKokilo-octets. Aucune modification de fichier. - Vérification :
Get-FichierVolumineux -Dossier /dossier-qui-n-existe-pasest refusé par la validation avant l'exécution ;-TailleMinKo 0est refusé parValidateRange. - Retour arrière : la fonction disparaît à la fermeture de la session (ou
Remove-Item function:Get-FichierVolumineux).
À savoir :
-LiteralPathtraite le chemin tel quel (pas de joker) : plus sûr avec des noms contenant[ou*.- Nommer ses fonctions
Verbe-Nomavec un verbe approuvé. Préférer retourner des objets plutôt qu'écrire du texte avecWrite-Host(qui sert à l'affichage seulement). returnn'est pas indispensable : tout ce qui est émis sur la sortie est retourné. Piège : une instruction qui renvoie un résultat non voulu pollue la sortie de la fonction.- Un script a un bloc
param()en tête, comme une fonction ;Set-StrictMode -Version Latestaide à détecter les variables non définies (comportement courant, non vérifié).
9. Gérer les erreurs
PowerShell distingue les erreurs non terminantes (la cmdlet continue, l'erreur est écrite sur le flux d'erreurs) et les erreurs terminantes (elles arrêtent l'instruction, voire le script). La page officielle about_Try_Catch_Finally (7.6) précise que try/catch attrape les erreurs terminantes de deux sortes (arrêtant l'instruction ou arrêtant le script).
-ErrorAction Stop: transforme une erreur non terminante d'une cmdlet en erreur terminante quecatchpourra attraper. Autres valeurs usuelles :Continue,SilentlyContinue,Ignore,Inquire(liste non relue surabout_CommonParameters).$ErrorActionPreference: valeur par défaut pour la session ou le script ; la pageabout_Try_Catch_Finallynote queSilentlyContinueouIgnorepeuvent même supprimer l'effet d'unthrow. À manier avec précaution.$_/$PSItemdanscatch: objet de typeErrorRecord(propriétésException,ScriptStackTrace,ErrorDetails).finally: s'exécute à tout coup, y compris après Ctrl+C selon la page ; sert à libérer des ressources.
try { Get-Content -LiteralPath ./fichier-absent.txt -ErrorAction Stop}catch { Write-Error "Lecture impossible : $($_.Exception.Message)"}finally { Write-Verbose "Fin du bloc" -Verbose}Bloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, dossier de test oùfichier-absent.txtn'existe pas. - Droits : utilisateur normal.
- Effet : tente de lire un fichier inexistant ; l'erreur est attrapée, un message est écrit sur le flux d'erreurs, puis le bloc
finallys'exécute. Aucune modification de fichier. - Vérification : le message « Lecture impossible : … » apparaît, suivi de la ligne verbeuse « Fin du bloc ». Sans
-ErrorAction Stop,catchne se déclenche pas : essayer. - Retour arrière : sans objet.
Attention : catch { } vide ou -ErrorAction SilentlyContinue partout masque les problèmes. Gérer l'erreur (message, code de sortie exit 1) ou laisser le script échouer. Pour qu'un script renvoie un code de sortie utile, terminer par exit <code> (comportement courant, non vérifié ici).
10. Fichiers, JSON et CSV
| Besoin | Cmdlet | Effet |
|---|---|---|
| lister | Get-ChildItem (-Recurse, -File, -Directory, -Force) | lecture |
| tester l'existence | Test-Path | lecture |
| lire | Get-Content, Get-Content -Raw | lecture |
| écrire | Set-Content, Out-File, Add-Content | écrit ou écrase |
| CSV | Import-Csv, Export-Csv | lecture / écrit |
| JSON | ConvertFrom-Json, ConvertTo-Json | transformation en mémoire |
| créer, copier, déplacer | New-Item, Copy-Item, Move-Item | modifie |
| supprimer | Remove-Item | supprime |
Sur PowerShell 7, l'encodage par défaut des fichiers texte est l'UTF-8 sans BOM d'après la documentation générale du produit (usage courant, non vérifié dans une page lue) : le préciser avec -Encoding utf8 quand on partage un fichier avec Windows PowerShell 5.1, dont le défaut était différent.
$donnees = @( [pscustomobject]@{ Nom = "alpha"; Taille = 3 }, [pscustomobject]@{ Nom = "beta"; Taille = 12 })$donnees | Export-Csv -LiteralPath ./essai.csv -NoTypeInformationImport-Csv -LiteralPath ./essai.csv | Where-Object { [int]$_.Taille -gt 5 }$donnees | ConvertTo-Json | Set-Content -LiteralPath ./essai.json(Get-Content -Raw -LiteralPath ./essai.json | ConvertFrom-Json).CountBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, dossier de test jetable ; données synthétiques.-NoTypeInformationn'est plus nécessaire dans PowerShell 7 d'après l'usage courant (non vérifié) ; sans effet nuisible ici. - Droits : écriture dans le dossier courant.
- Effet : crée (ou écrase)
essai.csvetessai.jsondans le dossier courant, relit le CSV en filtrant, relit le JSON et compte les éléments. Un CSV relu donne des chaînes de caractères : d'où[int]. - Vérification :
Import-Csvrenvoie une seule ligne (beta), et le compte JSON vaut2. - Retour arrière : supprimer les deux fichiers de test après relecture des noms :
Remove-Item -LiteralPath ./essai.csv, ./essai.json -WhatIf, puis sans-WhatIf.
À retenir : ConvertFrom-Json produit des objets : on n'exécute jamais le contenu d'un JSON (voir chapitre 14). Un JSON profond est tronqué à l'affichage par ConvertTo-Json selon la profondeur (-Depth, valeur par défaut non vérifiée) : la préciser quand on exporte des objets imbriqués.
11. -WhatIf, -Confirm et ShouldProcess
Les cmdlets qui modifient le système (Remove-Item, Set-Content, Stop-Process, Move-Item…) acceptent en général -WhatIf (montre ce qui serait fait, sans le faire) et -Confirm (demande validation). Selon la page « Everything you wanted to know about ShouldProcess » : -WhatIf affiche la description de l'action et ne l'exécute pas ; -Confirm pose la question avant chaque opération ; $ConfirmPreference vaut High par défaut et ConfirmImpact vaut Medium par défaut, si bien qu'une fonction n'interroge pas l'utilisateur sauf demande (ConfirmImpact = 'High' ou -Confirm).
Attention, effet notable. Cette commande a un effet notable. Lire le contexte, les droits et l’effet attendu indiqués après le bloc ; ne jamais l’exécuter sur un système réel sans validation, d’abord dans un environnement de test.
Remove-Item -LiteralPath ./essai.csv -WhatIfRemove-Item -LiteralPath ./essai.csv -ConfirmBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, dossier de test oùessai.csvexiste (chapitre 10). La sortie affichée en-WhatIfressemble à « What if: Performing the operation "Remove File" on target … » d'après la page citée. - Droits : suppression dans le dossier de test (droits de l'utilisateur).
- Effet : la première commande n'efface rien et décrit l'opération ; la seconde demande confirmation, et supprime le fichier si on répond Oui (Y).
- Vérification : après la première,
Test-Path ./essai.csvrenvoieTrue; après la seconde en répondant N, aussiTrue. - Retour arrière : la suppression ne passe pas par la corbeille et n'est pas annulable : aucune annulation. Garder une copie, ou travailler sur un fichier de test.
Attention : -WhatIf n'est fiable que si la cmdlet implémente correctement ShouldProcess. La page déconseille de faire confiance à l'héritage de -WhatIf d'un module de script à un autre. Assurez-vous qu'une commande de votre script le respecte (en cas de doute : -WhatIf seulement sur ce que vous avez testé, sinon un dossier de test).
Dans vos fonctions, activer ce mécanisme est simple :
function Remove-FichierEssai { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param([Parameter(Mandatory)][string]$Chemin) if ($PSCmdlet.ShouldProcess($Chemin, 'Supprimer')) { Remove-Item -LiteralPath $Chemin }}Remove-FichierEssai -Chemin ./essai.json -WhatIfBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, dossier de test ; schémaSupportsShouldProcess/$PSCmdlet.ShouldProcessrepris de la page « Everything you wanted to know about ShouldProcess » (consultée le 2026-10-17), avec ses précisions :ShouldProcessprès du changement,-Forceet-Confirm:$falsepour automatiser. - Droits : écriture dans le dossier de test pour la suppression ; aucune avec
-WhatIf. - Effet : déclare la fonction ; avec
-WhatIf, affiche « Supprimer » sur la cible sans rien supprimer. Sans-WhatIf, l'impactHighprovoquerait une demande de confirmation avantRemove-Item. - Vérification :
essai.jsonexiste toujours après l'appel avec-WhatIf. - Retour arrière : avec
-WhatIf, sans objet. Pour une vraie suppression : aucun retour arrière (pas de corbeille).
Précaution : habitude de travail : -WhatIf d'abord, lecture de la sortie, puis la même commande sans -WhatIf, dans un dossier de test.
12. Politique d'exécution : ce qu'elle est et n'est pas
D'après la page about_Execution_Policies (version 7.6, mise à jour le 2026-08-31) :
- la politique d'exécution est « une fonction de sécurité » qui contrôle les conditions de chargement des fichiers de configuration et d'exécution des scripts, mais elle n'est pas une frontière de sécurité : c'est une « défense en profondeur » ; la page donne l'exemple d'un utilisateur qui la contourne en tapant le contenu du script en ligne de commande ;
- l'application n'a lieu que sous Windows ; sur les systèmes non Windows, la politique par défaut est
Unrestrictedet ne peut pas être changée :Get-ExecutionPolicyrenvoieUnrestricted, le comportement correspond àBypass,Set-ExecutionPolicyexiste mais affiche un message indiquant que ce n'est pas pris en charge ; - sous Windows, les valeurs sont
AllSigned,Bypass,Default,RemoteSigned(défaut des Windows Server et poste client Windows en 7.x),Restricted,Undefined,Unrestricted, avec des portées (Process,CurrentUser,LocalMachine, stratégies de groupe).
À retenir : sur le Mac de Stéphane, la politique d'exécution ne protège de rien : n'importe quel script .ps1 lancé avec pwsh s'exécute. La protection repose sur la lecture du script avant exécution, sur les droits du compte, et sur la provenance du fichier. Sur Windows, elle aide à éviter les erreurs, pas à contrer un attaquant.
Get-ExecutionPolicyGet-ExecutionPolicy -ListBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwshsur macOS ; sortie attendue d'après la page :Unrestricted. - Droits : utilisateur normal.
- Effet : lecture de la politique effective. Aucune modification.
- Vérification : la valeur affichée correspond à la documentation ; si elle diffère, noter la valeur et la version de
pwsh. - Retour arrière : sans objet.
Attention : n'exécutez pas Set-ExecutionPolicy Bypass « pour que ça marche » sous Windows (copie de conseils trouvés sur le web) : cela supprime une garde, sans résoudre le vrai problème (script téléchargé non fiable). Sur macOS, cette commande n'a de toute façon pas d'effet (selon la page).
13. Modules et PowerShell Gallery : risques de chaîne d'approvisionnement
Un module regroupe des cmdlets et des fonctions. La PowerShell Gallery est, d'après Microsoft Learn, le dépôt central des modules, scripts et ressources DSC ; certains paquets sont écrits par Microsoft, d'autres par la communauté. Le module PowerShellGet (et son successeur PSResourceGet : non vérifié dans les pages lues) installe, met à jour et publie ces paquets.
Un module installé s'exécute avec vos droits : il peut lire vos fichiers, vos variables d'environnement, vos jetons. Installer un module, c'est exécuter le code de son auteur.
Attention : risques de la chaîne d'approvisionnement :
- usurpation de nom (typosquatting), compte d'auteur compromis, mise à jour malveillante d'un module légitime ;
- dépendances transitives : un module en installe d'autres ;
- un script « d'installation » qui s'exécute à l'import.
Précautions (bonnes pratiques générales, non vérifiées dans une page officielle consultée) :
- préférer les modules Microsoft ou d'éditeurs connus ; regarder le nombre de téléchargements, la date, l'auteur, le dépôt source ;
- lire la page du module sur la Gallery avant de l'installer ; chercher le dépôt public et le lire ;
- installer pour l'utilisateur courant (
-Scope CurrentUser), jamais avecsudosans nécessité ; - épingler une version précise (
-RequiredVersion) et noter laquelle ; - tester d'abord dans une machine ou un compte jetable ;
- ne pas ajouter de dépôt tiers ni passer à « Trusted » sans raison.
Get-Module -ListAvailableFind-Module -Name PSScriptAnalyzer -Repository PSGalleryBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh, accès à Internet pour la seconde commande ;Find-Moduleappartient à PowerShellGet (non vérifié, la commande équivalente de PSResourceGet estFind-PSResource). Le nomPSScriptAnalyzerest donné à titre d'exemple d'outil de lint : son adéquation est non vérifiée. - Droits : utilisateur normal ; aucune installation.
- Effet : la première liste les modules déjà présents sur le poste ; la seconde interroge la Gallery et affiche des métadonnées (version, auteur, description). Aucune modification locale ; la seconde commande envoie une requête réseau.
- Vérification : lire l'auteur et la version proposés ; comparer avec la page du paquet.
- Retour arrière : sans objet.
Attention : n'installez rien sans décision explicite ; Install-Module ou Install-PSResource écrit dans le dossier des modules et peut exécuter du code d'installation. Retirer : Uninstall-Module / Uninstall-PSResource (non testé ici).
14. Scripts sûrs
Un script PowerShell sûr, c'est surtout de la discipline :
- Commencer en lecture seule :
Get-*,Test-*,-WhatIf. Puis seulement passer à l'écriture. - Paramétrer plutôt que coder en dur :
param()typé, validé (chapitre 8). Set-StrictMode -Version Latestet$ErrorActionPreference = 'Stop'en tête de script pour échouer tôt (usage courant, non vérifié).SupportsShouldProcesspour toute fonction qui modifie quelque chose (chapitre 11).-LiteralPathplutôt que-Pathquand le chemin vient d'un utilisateur.- Pas de construction de commande par concaténation de texte, et jamais
Invoke-Expression(iex) sur une donnée externe.Invoke-Expressionexécute une chaîne comme du code : même risque queevalen shell. - Jamais
Invoke-WebRequest … | Invoke-Expressionouiwr … | iex: exécuter du code téléchargé sans l'avoir lu. - Les commandes natives (
git,ls…) se lancent avec leurs arguments séparés, sans passer par une chaîne construite. - Les données externes (JSON reçu, fichier CSV, contenu web) sont de la donnée, jamais du code.
- Écrire les journaux sans jetons ni mots de passe ; pas de
Write-Hostd'un secret.
Attention, effet notable. Cette commande a un effet notable. Lire le contexte, les droits et l’effet attendu indiqués après le bloc ; ne jamais l’exécuter sur un système réel sans validation, d’abord dans un environnement de test.
Get-Content -Raw ./script-telecharge.ps1Invoke-Expression (Get-Content -Raw ./script-telecharge.ps1)Bloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : exemple de ce qu'il ne faut pas faire avec un script non relu ; la deuxième ligne est donnée pour être reconnue et refusée. Ne pas la lancer sur un script dont on ne connaît pas l'auteur.
- Droits : ceux de l'utilisateur : le script aurait accès à tout ce que vous pouvez lire et écrire.
- Effet : la première ligne affiche le contenu (lecture seule : à faire d'abord) ; la seconde exécute ce contenu comme du code.
- Vérification : relire ligne à ligne la première sortie ; chercher les appels réseau, les suppressions, les écritures hors dossier, l'encodage obscurci (Base64).
- Retour arrière : aucun si le script a agi (fichiers supprimés, envoyés). D'où la règle : lire, puis exécuter un script de confiance depuis un fichier (
pwsh -File ./script.ps1), jamais viaiex.
15. Secrets : SecretManagement, SecureString et leurs limites
- Ne jamais écrire un mot de passe ou un jeton dans un script, un historique, un journal ou une URL. Les passer par une variable d'environnement, par un paramètre
[securestring]ou[pscredential], ou par un coffre. SecureString: type de chaîne chiffrée en mémoire sous Windows (DPAPI). La documentation générale de .NET déconseille aujourd'huiSecureStringpour les nouveaux développements, et sur macOS et Linux elle n'offre pas de chiffrement en mémoire équivalent : cette affirmation vient de connaissances générales et est non vérifiée ici, car la page de référence n'a pas été relue. ConsidérerSecureStringcomme une protection limitée, pas comme un coffre.Get-Credentialdemande un identifiant et un mot de passe à l'écran (interactif) : objetPSCredential. Convertir un mot de passe en clair avecConvertTo-SecureString -AsPlainText -Forceécrit le secret en clair dans la commande : à éviter.- SecretManagement et SecretStore (modules Microsoft.PowerShell) : d'après la page d'aperçu (mise à jour le 2026-06-22), SecretManagement est une couche d'abstraction (
Get-Secret,Set-Secret,Register-SecretVault) ; SecretStore est un coffre local qui chiffre un fichier pour l'utilisateur courant avec les API cryptographiques de .NET. La page indique que ces modules sont considérés comme « feature complete », qu'ils ne seront plus activement développés (corrections de sécurité et bugs critiques seulement), que le dépôt est archivé, et que les versions publiées sont SecretManagement 1.1.2 et SecretStore 1.0.6. Elle invite à évaluer chaque extension de coffre non écrite par Microsoft. - Sur le Mac de Stéphane, le Trousseau macOS est déjà le coffre de l'Orchestrator (
bin/secret get NOM,bin/avec-secrets) : un script PowerShell peut recevoir un secret par variable d'environnement le temps d'une commande plutôt que de le lire en clair. Une extension de coffre « KeyChain » est citée sur la page, mais elle est communautaire : non évaluée ici.
Get-SecretVaultGet-Command -Module Microsoft.PowerShell.SecretManagementBloc actif : la touche C copie la commande seule, sans invite ni sortie.
- Contexte : session
pwsh; lecture seule. Ces commandes ne fonctionnent que si le module SecretManagement est déjà installé ; sinonGet-Commandne renvoie rien. Le module n'est pas installé par ce cours. - Droits : utilisateur normal.
- Effet : liste les coffres enregistrés et les commandes du module. Aucune modification. Aucune valeur de secret n'est affichée.
- Vérification : sans module, les commandes signalent une erreur « non reconnue » (comportement attendu, non un problème).
- Retour arrière : sans objet.
Attention : Set-Secret, Register-SecretVault, Unregister-SecretVault modifient la configuration des secrets. Ne pas les essayer avec des secrets réels dans un cours ; utiliser un secret factice (valeur-de-test) et un coffre jetable, après avis de cyberagent pour tout usage réel.
16. Lecture seule d'abord : synthèse
Procédure à suivre pour toute nouvelle tâche :
- Décrire :
Get-Command,Get-Help,Get-Member. - Lire :
Get-*,Test-*,Measure-*. Regarder l'objet entier. - Filtrer à l'écran :
Where-Object/Select-Object, sans écrire. - Essai à blanc : même commande avec
-WhatIf. - Exécuter sur des données de test, dans un dossier jetable.
- Vérifier : relire le résultat (
Get-ChildItem,Test-Path) et le code de sortie ($?,$LASTEXITCODE: usage courant, non vérifié). - Seulement alors, appliquer à des données réelles, avec une sauvegarde.
Exercices et vérifications de fin de cours
Tous dans un dossier de test jetable, aux noms synthétiques.
- Version. Lancer
pwsh, relever$PSVersionTable.PSVersionet la comparer à la page des versions. - Découverte. Avec
Get-Command, trouver trois cmdlets dont le nom contientContent; lire l'aide de l'une d'elles. - Objet. Exécuter
Get-Item .etGet-Member; lister cinq propriétés. - Pipeline. Reproduire le chapitre 5 : fichiers de plus d'1 Ko triés par taille.
- Format. Afficher le même résultat en
Format-TableetFormat-List, puis expliquer pourquoiFormat-*va en dernier. - Structures. Créer une table de hachage et un tableau, ajouter un élément, relire la taille.
- Fonction. Écrire
Get-FichierVolumineux(chapitre 8) ; provoquer les deux refus de validation. - Erreur. Reproduire l'exemple du chapitre 9 avec et sans
-ErrorAction Stop. - CSV et JSON. Exporter deux objets synthétiques, les relire, les filtrer.
- WhatIf. Lancer
Remove-Item … -WhatIfsur un fichier de test, puis le supprimer vraiment après relecture du nom. - ShouldProcess. Ajouter
SupportsShouldProcessà une fonction qui écrit un fichier de test. - Politique d'exécution. Lire
Get-ExecutionPolicy -Listet expliquer, en deux phrases, pourquoi ce n'est pas une frontière de sécurité. - Modules. Choisir un module de la Gallery et remplir la liste de contrôle du chapitre 13 sans l'installer.
- Données non fiables. Citer trois constructions interdites avec une donnée externe et leur remplaçant.
Critères de réussite
- Distinguer
pwsh(7.x) depowershell.exe(5.1, Windows) et citer deux différences. - Expliquer en quoi un tube d'objets diffère d'un tube de texte.
- Écrire un
Where-Object, unSelect-Objectet unSort-Objectenchaînés. - Placer
Format-*en dernier et exporter avant de formater. - Déclarer une fonction avec
[CmdletBinding()]et une validation. - Attraper une erreur avec
-ErrorAction Stopettry/catch/finally. - Utiliser
-WhatIfavant toute commande à effet. - Dire que la politique d'exécution n'est pas une frontière de sécurité et qu'elle n'est pas appliquée sur macOS.
- Nommer les risques d'un module de la Gallery et trois précautions.
- Expliquer pourquoi un secret n'est pas écrit en clair, et citer une limite de
SecureString. - Citer le périmètre des sources (documentation 7.6 en ligne, 17 octobre 2026) sans le confondre avec la version installée.
Points non vérifiés ou à confirmer
- Versions de macOS et de PowerShell sur le Mac de Stéphane ; version qu'il souhaite viser (7.4 LTS, 7.5, 7.6 LTS ?). Les pages lues listent 7.6 (LTS) comme défaut ; le numéro de correctif diffère entre la page des versions GitHub (v7.6.7) et la page d'installation (7.6.6).
- Le contenu de ce cours repose sur la lecture, le 17 octobre 2026, de huit pages seulement : différences 5.1 / 7.x, installation sur macOS, politique d'exécution, ShouldProcess,
try/catch/finally, plus l'aperçu de SecretManagement, de la PowerShell Gallery et la page des versions GitHub. Les pages lues par un outil de synthèse automatique sont citées en traduction libre. - Non relues, à reconfronter :
about_Pipelines,about_Comparison_Operators,about_Arrays,about_Hash_Tables,about_Functions_Advanced*,about_CommonParameters,about_Quoting_Rules,about_Automatic_Variables,about_Aliases,Get-Verbet les verbes approuvés, la page de ligne de commande depwsh. Les chapitres 2 à 8 et 10 reflètent le langage tel que généralement connu et sont donc à vérifier. - Disponibilité sur macOS de chaque cmdlet citée (
Out-GridView: Windows,Get-Process: propriétéCPUet son unité, aliasls/cat). - Encodage par défaut,
-NoTypeInformation, profondeur par défaut deConvertTo-Json,Update-Help, droits requis parUpdate-Help. SecureStringsur macOS (absence de chiffrement équivalent à Windows),ConvertTo-SecureString, extension communautaire « KeyChain ».- PSResourceGet comme successeur de PowerShellGet,
Install-PSResource,Find-PSResource, signatures et vérification des paquets de la Gallery ; liste de précautions du chapitre 13 : bonnes pratiques générales, non issues d'une source officielle lue. - Le comportement de
-WhatIfhors des cmdlets Microsoft ; la fiabilité deShouldProcessdes modules tiers. - Aucune commande de ce cours n'a été exécutée.
Sources officielles
Toutes consultées le 17 octobre 2026. Documentation Microsoft Learn affichant PowerShell 7.6 comme version par défaut ; SecretManagement : modules indépendants (SecretManagement 1.1.2, SecretStore 1.0.6 d'après la page) ; page des versions GitHub : v7.6.7 stable (13 octobre 2026), 7.7.0-preview.5 en préversion.