Arrêter d'utiliser Write-Host — Conception des flux de sortie et de la journalisation dans PowerShell
· Go Komura · PowerShell, Windows, Journalisation, Amélioration opérationnelle, Automatisation, Script, Conception, Maintenabilité
« Le script fonctionne, mais on ne sait pas ce qui s’est passé en cas d’échec » — c’est la demande la plus fréquente concernant les scripts PowerShell mis en production. Et en remontant à la cause, on tombe presque toujours sur la même structure : l’état du traitement n’est exprimé que par Write-Host, et il ne reste rien pour une exécution nocturne où personne ne regardait l’écran.
PowerShell dispose de six types de flux de sortie, chacun destiné à un public différent : renvoyer une valeur, informer un humain, ou n’être utile que pendant une investigation. En les répartissant consciemment, le même script devient accueillant en exécution interactive et lisible par une machine en exécution sans surveillance. À l’inverse, tout faire passer par Write-Host ne fait qu’accumuler des informations inutilisables comme valeurs et absentes des journaux.
Cet article présente le rôle des six flux, la bonne place de Write-Host, le mécanisme de pollution des valeurs de retour des fonctions, la manière de contrôler le niveau de détail depuis l’appelant, et jusqu’au modèle de journalisation structurée utilisable en production.
1. La conclusion, d’abord
- PowerShell compte six flux de sortie. Succès (1), erreur (2), avertissement (3), détaillé (4), débogage (5) et information (6) ; chacun peut être redirigé par son numéro.
*>désigne tous les flux.1 - Depuis PowerShell 5.0,
Write-Hostécrit dans le flux d’information. Cela a rendu possible la redirection avec6>et la capture avec-InformationVariable. Avant cela, ni capture ni suppression n’étaient possibles.2 Write-Hostest réservé à « l’affichage destiné à un humain ». Il ne convient pas pour renvoyer une valeur. La valeur transmise au pipeline passe parWrite-Output(ou une sortie nue).23- Une fonction renvoie tous les objets produits en interne. La présence ou non d’un
returnn’y change rien. La pratique standard consiste à jeter la sortie inutile avec$null = ....4 - La progression relève de
Write-Progress, l’avancement du traitement deWrite-Verbose. L’affichage de progression n’est pas un flux de données que l’on peut rediriger.5 - Une fonction dotée de
[CmdletBinding()]acquiert automatiquement les paramètres communs comme-Verbose,-Debuget-InformationAction. La bonne approche consiste à laisser l’appelant décider du niveau de détail.67 - Il vaut la peine de retenir les valeurs par défaut.
$VerbosePreference,$DebugPreferenceet$InformationPreferencevalent SilentlyContinue ;$WarningPreferenceet$ErrorActionPreferencevalent Continue.8 - Structurez (1 ligne = 1 JSON) les journaux que vous voudrez analyser par la suite. Si vous voulez reproduire ce qui s’affichait à l’écran, combinez cela avec
Start-Transcript.9
Les versions de référence de cet article, et les différences sous 5.1
Sur le terrain des services informatiques, Windows PowerShell 5.1 reste majoritaire. Précisons d’abord sur quelle version reposent les explications de cet article.
| Description | Version de référence | Sous Windows PowerShell 5.1 |
|---|---|---|
Les six flux de sortie et la redirection numérotée, *> |
Identique sous 5.1 et sous PowerShell 7 | S’applique tel quel1 |
Write-Host écrit dans le flux d’information (n° 6) (capturable avec 6> ou -InformationVariable) |
PowerShell 5.0 et versions ultérieures (chapitre 3) | 5.1 étant postérieure à 5.0, cela s’applique tel quel2 |
Write-Information et -InformationAction / -InformationVariable |
PowerShell 5.0 et versions ultérieures (chapitre 4) | S’applique tel quel7 |
Le fait qu’une fonction renvoie toute sa sortie interne, la suppression avec $null = ... |
Indépendant de la version (chapitre 5) | S’applique tel quel4 |
Le traitement de 2>&1 pour les commandes externes (commandes natives) |
Décrit comme le comportement de PowerShell 7.4 et versions ultérieures (chapitre 6) | Ne s’applique pas. Vérifiez toujours, avec la version que vous exécutez réellement, l’écriture qui trie par type la sortie d’une commande externe |
Contrôler Write-Progress avec le paramètre commun -ProgressAction |
PowerShell 7.4 et versions ultérieures5 | Inutilisable. Le contrôle se fait avec $ProgressPreference (c’est cette approche qui est décrite au chapitre 8) |
| Le code d’exemple distribué en fin d’article | Exécuté et vérifié sous PowerShell 7.6 (14 tests Pester) | — |
En somme, les chapitres 2 à 5 ainsi que le chapitre 7 s’appliquent tels quels sous 5.1. Les deux seuls endroits où il faut être attentif à la version sont la redirection des commandes externes (chapitre 6) et la méthode de contrôle de l’affichage de progression (chapitre 8).
2. Les six flux, et leurs destinataires
Commençons par récapituler en un seul schéma quelle commande d’écriture aboutit où.
flowchart LR
O["Write-Output / sortie nue"]
OTH["Write-Error / Write-Warning<br/>Write-Verbose / Write-Debug<br/>Write-Information / Write-Host"]
S1["1 Flux de succès"]
S26["2 Erreur / 3 Avertissement / 4 Détaillé<br/>5 Débogage / 6 Information"]
PIPE["Transmis au traitement suivant<br/>pipeline, affectation à une variable"]
HOST["Affiché à l'écran<br/>l'affichage par défaut dépend des variables d'environnement"]
FILE["Peut être conservé dans un fichier<br/>redirection numérotée, variable de capture"]
O --> S1
OTH --> S26
S1 --> PIPE
S1 --> FILE
S26 --> HOST
S26 --> FILE
Seul le flux de succès est transmis au traitement suivant. Les cinq autres s’affichent à l’écran ou se capturent via une redirection ou un paramètre -*Variable, mais ne passent jamais par le pipeline. Se tromper dans l’embranchement de gauche (avec quelle commande écrire) se manifeste toujours, sous une forme ou une autre : une valeur qui n’arrive pas, ou une information absente du journal. Les numéros servent à indiquer une redirection, comme dans 3> warnings.log (chapitre 6).
| # | Flux | Commande d’écriture | Destinataire prévu | Réglage par défaut |
|---|---|---|---|---|
| 1 | Succès (Success) | Write-Output / sortie nue |
Le traitement suivant (pipeline) | — |
| 2 | Erreur (Error) | Write-Error / lever une exception |
Humain + supervision | Continue |
| 3 | Avertissement (Warning) | Write-Warning |
Humain | Continue |
| 4 | Détaillé (Verbose) | Write-Verbose |
Humain en cours d’investigation | SilentlyContinue |
| 5 | Débogage (Debug) | Write-Debug |
Développeur | SilentlyContinue |
| 6 | Information (Information) | Write-Information / Write-Host |
Humain + enregistrement | SilentlyContinue |
Le fait que le flux d’information ait SilentlyContinue comme valeur par défaut alors que Write-Host s’affiche quand même à l’écran n’est pas une contradiction. Write-Host fait exception à lui seul : Microsoft Learn indique explicitement que « la variable d’environnement $InformationPreference et le paramètre commun -InformationAction n’affectent pas les messages de Write-Host ».2 Autrement dit, Write-Information ne s’affiche pas par défaut, mais Write-Host s’affiche même par défaut, et les seuls moyens de le supprimer sont -InformationAction Ignore et la redirection avec 6>.
La ligne la plus importante de ce tableau est la première. Le flux de succès n’est pas l’endroit où écrire des « messages destinés à un humain ». Y écrire une chaîne destinée à un humain fait que, dès que vous chaînez cette fonction avec |, une chaîne inattendue s’écoule dans le traitement suivant.
function Get-KsTargetFile {
Write-Output "Recherche des cibles en cours..." # [MAUVAIS] se mélange à la valeur de retour
Get-ChildItem -Path $path -Filter '*.csv'
}
# L'appelant attend un tableau de FileInfo, mais une chaîne se retrouve en tête
$files = Get-KsTargetFile
$files[0].FullName # → vide (car le premier élément est une chaîne)
La bonne pratique consiste à envoyer les comptes rendus de progression vers le flux détaillé ou le flux d’information.
function Get-KsTargetFile {
[CmdletBinding()]
param([string] $Path)
Write-Verbose "Recherche des cibles : $Path" # ne s'affiche que si -Verbose est précisé
Get-ChildItem -Path $Path -Filter '*.csv' # la valeur de retour ne contient que des FileInfo
}
3. Write-Host est-il « à bannir » ?
L’idée selon laquelle « il ne faut jamais utiliser Write-Host » s’est autrefois largement répandue, mais la situation a changé dans les versions actuelles de PowerShell. Depuis PowerShell 5.0, Write-Host est implémenté comme une écriture vers le flux d’information (n° 6), ce qui permet de le rediriger avec 6> ou de le capturer avec -InformationVariable.2 La critique d’époque, selon laquelle il « ne pouvait s’afficher qu’à l’écran, sans jamais pouvoir être récupéré après coup », ne s’applique plus. Cela dit, comme mentionné au chapitre 2, même si la valeur par défaut du flux d’information est SilentlyContinue, seul l’affichage de Write-Host ne disparaît pas : il n’est pas affecté par $InformationPreference ni par -InformationAction (la seule exception étant -InformationAction Ignore, qui supprime aussi la sortie de Write-Host). « Pouvoir désormais le capturer » et « s’afficher à l’écran par défaut » coexistent parfaitement.2
Cela dit, son champ d’application reste limité.
Les situations où Write-Host convient
- Dans un outil utilisé de manière interactive, quand vous voulez afficher des titres ou des séparateurs colorés (
-ForegroundColor) - Quand vous voulez indiquer à l’utilisateur « ce que ce script s’apprête à faire »
- Quand l’objectif est l’affichage décoratif lui-même, et non une valeur de traitement
Les situations où il ne faut pas utiliser Write-Host
- Quand vous voulez transmettre une valeur comme retour de fonction (→
Write-Output) - Quand vous voulez conserver un journal opérationnel destiné à être analysé plus tard (→ journalisation structurée, ou
Write-Information) - Quand vous voulez que l’appelant puisse activer ou désactiver l’affichage (→
Write-Verbose)
Dans un script en exécution sans surveillance, il n’y a de toute façon aucune destination d’affichage. Un script qui n’exprime son état qu’avec Write-Host devient, dès l’instant où il est lancé depuis le planificateur de tâches, un « script dont on ne comprend rien ». C’est précisément le sens du titre de cet article.
4. Laisser le contrôle à l’appelant — [CmdletBinding()] et les paramètres communs
La vraie valeur de Write-Verbose réside dans le fait que c’est l’appelant qui décide de l’affichage ou non. Il suffit d’ajouter [CmdletBinding()] à une fonction pour que les paramètres communs comme -Verbose, -Debug, -WarningAction, -InformationAction et -ErrorAction deviennent automatiquement disponibles.67
function Invoke-KsImport {
[CmdletBinding()]
param(
[Parameter(Mandatory)] [string] $CsvPath
)
Write-Verbose "Début de l'import : $CsvPath" # ne s'affiche pas par défaut
Write-Information "Import : $CsvPath" -Tags 'KsImport' # ne s'affiche pas par défaut (mais peut être capturé)
$rows = Import-Csv -Path $CsvPath
if ($rows.Count -eq 0) {
Write-Warning "Aucun élément à importer dans $CsvPath" # s'affiche par défaut
return
}
Write-Verbose "Traitement de $($rows.Count) élément(s)"
$rows | ForEach-Object { ConvertTo-KsRecord $_ } # seule cette valeur est retournée
}
# Exécution normale : seul l'avertissement s'affiche, la valeur de retour contient les enregistrements
$records = Invoke-KsImport -CsvPath 'D:\in\orders.csv'
# Pendant une investigation : on veut aussi voir la progression
$records = Invoke-KsImport -CsvPath 'D:\in\orders.csv' -Verbose
# Ne capturer que le flux d'information dans une variable, pour l'écrire ensuite dans un fichier journal
$records = Invoke-KsImport -CsvPath 'D:\in\orders.csv' -InformationVariable info
$info | ForEach-Object { $_.MessageData } | Add-Content -Path $logPath
On rencontre souvent des implémentations qui créent leur propre variable $LogLevel et branchent avec une instruction if, mais s’appuyer sur le mécanisme standard est plus court et transmet mieux l’intention aux autres. En effet, le fait qu’ajouter -Verbose fasse apparaître les détails est une convention partagée par tous les utilisateurs de PowerShell.
Notez que les variables d’environnement comme $VerbosePreference s’appliquent à la portée courante et aux portées enfants.8 Appeler une fonction avec -Verbose fait que les applets de commande appelées à l’intérieur commencent elles aussi à produire une sortie détaillée, ce qui peut faire apparaître plus de sortie que prévu.
5. La pollution des valeurs de retour des fonctions — un piège propre à PowerShell
Une fonction PowerShell renvoie tous les objets produits en interne, même sans return explicite.4 C’est une spécification puissante, mais c’est aussi la source d’accidents la plus fréquente.
function New-KsWorkFolder {
param([string] $Path)
New-Item -Path $Path -ItemType Directory # [Piège] un DirectoryInfo se mélange à la valeur de retour
$list = [System.Collections.Generic.List[string]]::new()
$list.Add('log') # [Piège 2] .Add() est void, donc pas de dégât réel
$sb = [System.Text.StringBuilder]::new()
$sb.Append('x') # [Piège 3] le StringBuilder lui-même est renvoyé
return $Path
}
$p = New-KsWorkFolder -Path 'D:\work' # $p devient un tableau de 3 éléments (DirectoryInfo, StringBuilder, string)
La solution consiste à « jeter la sortie inutile ». Il existe trois manières de l’écrire, mais $null = ... est la plus légère.
$null = New-Item -Path $Path -ItemType Directory # recommandé
New-Item -Path $Path -ItemType Directory | Out-Null # plus lent, à cause du pipe
[void] $sb.Append('x') # souvent utilisé pour les méthodes .NET
Écrire un test permet de repérer immédiatement ce comportement. L’importance des tests qui « figent la forme de la valeur de retour » est traitée dans « Mettre en place des tests PowerShell avec Pester ».
6. Redirection et capture
Les flux peuvent être redirigés individuellement par leur numéro.1
.\Invoke-NightlyExport.ps1 3> warnings.log # seuls les avertissements vers un fichier séparé
.\Invoke-NightlyExport.ps1 4>&1 | Tee-Object -FilePath run.log # fusionner le détaillé dans le flux de succès
.\Invoke-NightlyExport.ps1 *> all.log # tous les flux vers un seul fichier
.\Invoke-NightlyExport.ps1 2>&1 | Where-Object { $_ -is [System.Management.Automation.ErrorRecord] }
> écrase, >> ajoute. Cela dit, gardez à l’esprit que fusionner des flux par redirection mélange les types. Comme dans l’exemple ci-dessus, quand vous fusionnez le flux d’erreur d’un script ou d’une fonction PowerShell, ses éléments restent des ErrorRecord, ce qui permet de les trier par type comme ci-dessus.
En revanche, le cas de 2>&1 pour un programme externe (commande native) est différent. Depuis PowerShell 7.4, la sortie redirigée est traitée comme un flux d’octets, et devient une chaîne de caractères après fusion, si bien que le tri par ErrorRecord ne fonctionne plus. Si vous voulez distinguer stdout et stderr d’une commande externe, recevez-les séparément, sans les fusionner (voir « Appeler correctement un exe externe depuis PowerShell »).
Le moyen le plus sûr de vérifier que la séparation se comporte comme prévu est de l’essayer soi-même, une fois. Un court extrait qui produit à la fois le flux de succès et le flux d’avertissement permet de le vérifier.
# Seuls les avertissements vers un fichier séparé. Seul 'données' reste à l'écran
& { Write-Output 'données'; Write-Warning 'avertissement' } 3> warnings.log
Get-Content warnings.log # contient le message d'avertissement. 'données' n'y figure pas
# Tous les flux vers un seul fichier
& { Write-Output 'données'; Write-Warning 'avertissement'; Write-Verbose 'détail' -Verbose } *> all.log
Get-Content all.log # les trois sorties s'y retrouvent ensemble
Si warnings.log reste vide alors que vous avez ajouté 3>, c’est que ce message n’a pas été écrit dans le flux d’avertissement (s’il est écrit avec Write-Host, c’est 6> qu’il faut utiliser). Pour diagnostiquer « ce qui aurait dû apparaître dans le journal n’y est pas », le plus rapide est de commencer par ces deux lignes.
Notez que *> est pratique, mais tout regrouper rend difficile un re-tri ultérieur par flux. Si vous voulez agréger cela mécaniquement, envoyez chaque flux vers un fichier séparé, ou optez pour la journalisation structurée du chapitre suivant.
Si vous voulez conserver l’intégralité de la trace d’exécution, Start-Transcript est la solution la plus simple. Elle enregistre en texte les commandes et la sortie de la session, ce qui permet de reproduire après coup « ce qui s’affichait à l’écran à ce moment-là ».9
Start-Transcript -Path "C:\Logs\export_$(Get-Date -f yyyyMMdd_HHmmss).log" -Append
try { Invoke-KsExport }
finally { Stop-Transcript }
7. Rendre les journaux analysables ultérieurement — la journalisation structurée
Un journal lu par un humain et un journal agrégé par une machine sont deux choses différentes. Quand vous voulez savoir « combien de fois cette erreur est-elle survenue le mois dernier », un texte au format libre devient une lutte d’endurance contre grep. En écrivant 1 ligne = 1 JSON (JSON Lines), l’agrégation peut se faire entièrement avec PowerShell seul.
function Write-KsLog {
[CmdletBinding()]
param(
[Parameter(Mandatory)] [ValidateSet('INFO','WARN','ERROR')] [string] $Level,
[Parameter(Mandatory)] [string] $Message,
[hashtable] $Data,
[string] $Path = $script:KsLogPath
)
$entry = [ordered]@{
ts = (Get-Date).ToString('o') # ISO 8601, facile à trier et à recouper
level = $Level
message = $Message
script = $MyInvocation.ScriptName
host = $env:COMPUTERNAME
user = $env:USERNAME
}
# Les informations supplémentaires vont sous data. Les mélanger au niveau
# racine ferait que si l'appelant passe une clé comme level ou user, elle écraserait les champs de base
if ($Data) { $entry['data'] = $Data }
# -Compress pour tenir sur une ligne. L'ajout se fait avec Add-Content (UTF-8)
$entry | ConvertTo-Json -Compress -Depth 5 | Add-Content -Path $Path -Encoding utf8
# L'affichage destiné à un humain s'appuie sur le mécanisme standard (s'affiche à l'écran mais ne renvoie pas de valeur)
switch ($Level) {
# -ErrorAction n'est pas précisé ici. Le fixer ici empêcherait
# l'appelant de le transformer en erreur fatale avec -ErrorAction Stop
'ERROR' { Write-Error $Message }
'WARN' { Write-Warning $Message }
default { Write-Verbose $Message }
}
}
# Exemple d'utilisation
Write-KsLog -Level INFO -Message 'Import terminé' -Data @{ rows = 1250; file = 'orders.csv'; ms = 4210 }
# → {"ts":"...","level":"INFO","message":"Import terminé","script":"...","host":"...","user":"...",
# "data":{"rows":1250,"file":"orders.csv","ms":4210}}
L’agrégation se présente ainsi.
Get-Content 'C:\Logs\ks.log' |
ForEach-Object { $_ | ConvertFrom-Json } |
Where-Object { $_.level -eq 'ERROR' -and [datetime]$_.ts -ge (Get-Date).AddDays(-30) } |
Group-Object message | Sort-Object Count -Descending | Select-Object Count, Name
Il est aussi possible de s’appuyer sur l’infrastructure de journalisation standard de Windows (journal des événements, ETW). C’est l’option la plus avantageuse si vous envisagez une intégration avec des outils de supervision ou une collecte depuis plusieurs machines. La comparaison de ces conceptions est résumée dans « Journal des événements Windows, ETW et journalisation structurée », et la gestion des générations de fichiers journaux dans « PowerShell avancé — investigation, archivage et mise en rapport des journaux ».
8. Le traitement de l’affichage de progression
Write-Progress s’appuie sur la fonctionnalité d’affichage de progression de l’hôte : ce n’est pas un flux de données que l’on peut rediriger.5 Autrement dit, il ne peut pas être conservé dans un journal. En exécution sans surveillance, il n’y a aucune destination d’affichage, et selon l’environnement, le coût de la mise à jour de la progression peut ne pas être négligeable.
# Arrêter l'affichage de progression en tête d'un script en exécution sans surveillance
$ProgressPreference = 'SilentlyContinue'
Si vous voulez conserver la progression dans un journal opérationnel, il est plus pratique de n’écrire que des jalons dans le flux détaillé.
$i = 0
foreach ($row in $rows) {
$i++
if ($i % 100 -eq 0) { Write-Verbose "$i / $($rows.Count) terminé(s)" }
...
}
9. Les bonnes pratiques (tableau de décision)
| Information à produire | À utiliser | Raison |
|---|---|---|
| Valeur transmise au traitement suivant | Write-Output / sortie nue |
Le flux de succès est réservé aux données3 |
| Avancement du traitement (à voir seulement en investigation) | Write-Verbose |
Contrôlé par l’appelant avec -Verbose7 |
| Événement à enregistrer pour l’exploitation | Write-Information + journalisation structurée |
Capturable avec -InformationVariable2 |
| Affichage décoratif d’un outil interactif | Write-Host |
Capturable aussi, car il passe par le flux d’information2 |
| Événement attendu mais nécessitant de l’attention | Write-Warning |
S’affiche par défaut, capturable avec -WarningVariable8 |
| Échec | Write-Error / throw |
Voir l’article dédié pour la gestion des erreurs |
| État interne en cours de développement | Write-Debug |
Uniquement quand -Debug est ajouté7 |
| Progression | Write-Progress (en interactif seulement) |
Ne se conserve pas dans un journal. À arrêter en exécution sans surveillance5 |
| Trace d’exécution intégrale | Start-Transcript |
À combiner comme filet de sécurité avec votre propre journalisation9 |
10. Conclusion
- La sortie de PowerShell se répartit en six flux. Le flux de succès est réservé aux données ; y mélanger des messages destinés à un humain casse la valeur de retour.
- Depuis PowerShell 5.0,
Write-Hostécrit dans le flux d’information et est donc capturable, mais il ne convient ni pour renvoyer une valeur ni pour la journalisation opérationnelle. - Une fonction renvoie tout ce qu’elle a produit en interne. La pratique standard consiste à jeter la sortie inutile avec
$null = .... - En ajoutant
[CmdletBinding()]et en utilisantWrite-Verbose/Write-Information, vous pouvez laisser le contrôle du niveau de détail à l’appelant. C’est plus court qu’une variable de niveau de journalisation maison, et l’intention se transmet mieux. - Pour un journal destiné à être agrégé plus tard, optez pour une journalisation structurée en 1 ligne = 1 JSON. Si l’objectif est de reproduire l’écran, combinez cela avec
Start-Transcript. - L’affichage de progression n’étant pas un flux de données, il ne se conserve pas dans un journal. En exécution sans surveillance, il est pratique de l’arrêter avec
$ProgressPreference = 'SilentlyContinue'.
Téléchargement du code d’exemple
Le code traité dans cet article est distribué sous une forme prête à l’emploi. Il comprend la journalisation structurée en 1 ligne = 1 JSON et l’écriture de fonctions qui ne polluent pas leur valeur de retour.
Télécharger le code d’exemple (zip)
Les exemples de cet article ont été effectivement exécutés et vérifiés sous PowerShell 7.6 (14 tests Pester). En exécutant Invoke-SampleTests.ps1 inclus dans le zip, vous pouvez reproduire la même vérification chez vous.
# Analyse syntaxique + analyse statique + tests Pester
./Invoke-SampleTests.ps1
Les valeurs de configuration (chemins, noms de serveurs, ID de locataire, etc.) sont données à titre d’exemple. Ne les exécutez pas telles quelles en production : adaptez-les à votre propre environnement.
Articles connexes
- Gestion des erreurs et conception des relances dans PowerShell — des pièges où try/catch ne fonctionne pas jusqu’aux bonnes pratiques d’exit code et de retry
- Conception des arguments et modularisation des scripts PowerShell — d’un « script qui fonctionne » à un « script que l’on peut transmettre »
- PowerShell avancé — automatiser en toute sécurité l’investigation, l’archivage et la mise en rapport des journaux
- Journal des événements Windows, ETW et journalisation structurée
- Mettre en place des tests PowerShell avec Pester — un modèle pratique pour rendre les scripts d’exploitation plus résistants à la casse
- Exigences minimales d’un enregistreur de journaux personnalisé et liste de contrôle pour les tests d’intégration
Domaines de conseil associés
合同会社小村ソフト (Komura Software LLC) prend en charge la révision de la conception des journaux pour les scripts d’exploitation, la résolution de situations où « on ne sait pas pourquoi cela a échoué », et la mise en place d’une infrastructure de journalisation qui alimente la supervision et l’agrégation.
- Conseil technique et revue de conception
- Investigation des anomalies et analyse des causes
- Modification et maintenance de logiciels Windows existants
- Contact
Références
-
Microsoft Learn, about_Redirection. Sur le fait que PowerShell possède les flux succès, erreur, avertissement, détaillé, débogage et information, chacun identifié par un numéro, sur la redirection vers un fichier avec
>et>>, sur la fusion vers un autre flux avecn>&1, et sur la redirection de tous les flux avec*>. ↩ ↩2 ↩3 -
Microsoft Learn, Write-Host. Sur le fait que, depuis PowerShell 5.0, Write-Host est devenu un wrapper de Write-Information qui écrit dans le flux d’information, rendant possible la redirection avec 6>, sur le fait que la variable d’environnement $InformationPreference et le paramètre commun -InformationAction n’affectent pas les messages de Write-Host (l’exception étant -InformationAction Ignore), ce qui explique qu’il s’affiche à l’écran même par défaut, sur la mise en forme via -ForegroundColor / -BackgroundColor, et sur le fait que la sortie n’est pas transmise au pipeline. En lien avec cela, Write-Information permet une écriture explicite dans le flux d’information et sa classification via -Tags. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Write-Output. Sur le fait d’envoyer un objet vers le flux de succès (le pipeline), et sur le fait que le résultat d’une expression est produit de la même manière même sans appel explicite. ↩ ↩2
-
Microsoft Learn, about_Return. Sur le fait qu’une fonction PowerShell renvoie à l’appelant tous les objets produits en son sein, avec ou sans return, et sur le fait que return est une syntaxe permettant de renvoyer une valeur tout en quittant la portée courante. ↩ ↩2 ↩3
-
Microsoft Learn, Write-Progress. Sur le fait de produire l’avancement d’une commande comme un affichage de progression de l’hôte, sur le contrôle de cet affichage via $ProgressPreference, et sur le fait qu’à partir de PowerShell 7.4, ce contrôle est aussi possible via le paramètre commun -ProgressAction. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, about_Functions_CmdletBindingAttribute. Sur le fait qu’une fonction avancée dotée de l’attribut [CmdletBinding()] se comporte comme une applet de commande compilée, et que les paramètres communs deviennent automatiquement disponibles. ↩ ↩2
-
Microsoft Learn, about_CommonParameters. Sur le comportement de -Verbose / -Debug / -WarningAction / -InformationAction / -ErrorAction et des paramètres -*Variable correspondants, ainsi que sur leur relation avec les variables d’environnement. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, about_Preference_Variables. Sur le fait que les valeurs par défaut de $VerbosePreference, $DebugPreference et $InformationPreference sont SilentlyContinue, que celles de $WarningPreference et $ErrorActionPreference sont Continue, sur le contrôle de l’affichage de progression via $ProgressPreference, et sur le fait que ces variables s’appliquent à la portée courante et aux portées enfants. ↩ ↩2 ↩3
-
Microsoft Learn, Start-Transcript. Sur l’enregistrement des commandes de la session et de la sortie de la console dans un fichier texte, sur l’ajout via -Append, et sur l’arrêt via Stop-Transcript. ↩ ↩2 ↩3
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Où regarder quand un script PowerShell est lent — les points clés sur les tableaux, le pipeline et le rapprochement de données
Ce guide passe en revue les causes classiques de lenteur des scripts PowerShell : pourquoi l'opérateur += sur un tableau devient O(n²), l...
Le traitement parallèle dans PowerShell — Choisir entre ForEach-Object -Parallel et les jobs
Ce guide présente, d'un point de vue pratique, les différences et les usages respectifs de ForEach-Object -Parallel, Start-ThreadJob et S...
Gérer les informations d'identification en toute sécurité sous PowerShell — bannir les mots de passe en clair de vos scripts
Un guide pratique pour faire migrer les mots de passe en clair d'un script PowerShell vers un stockage sécurisé : la réalité et les limit...
Conception des paramètres et modularisation des scripts PowerShell — Du « script qui fonctionne » au « script que l'on peut transmettre »
Ce guide organise les étapes pour élever la qualité d'un script PowerShell jusqu'à pouvoir le transmettre à d'autres personnes. Il couvre...
Gestion des erreurs et conception des nouvelles tentatives sous PowerShell — du piège du try/catch aux bonnes pratiques d'exit code et de retry
Cet article présente, du point de vue pratique, la différence entre erreurs terminales et non terminales sous PowerShell, le piège du try...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Conseil technique et revue de conception
Clarification de la stratégie de modification, de la conception et du traitement des actifs existants.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Ne faut-il jamais utiliser Write-Host ?
- Ce n'est pas une interdiction : il est plus juste de dire que son usage est limité. Depuis PowerShell 5.0, Write-Host écrit dans le flux d'information (n° 6), ce qui permet désormais de le rediriger avec 6> ou de le capturer avec -InformationVariable. Cela dit, c'est une commande conçue pour toujours s'afficher à l'écran par défaut, et elle ne convient pas quand on veut faire circuler une valeur dans le pipeline. La règle de répartition est la suivante : pour un affichage décoratif destiné à un humain dans un outil interactif, utilisez Write-Host ; pour la progression du traitement ou des informations complémentaires, Write-Verbose ou Write-Information ; pour une valeur transmise au traitement suivant, Write-Output (ou une sortie nue).
- Des valeurs indésirables se mélangent à la valeur de retour de ma fonction.
- C'est parce qu'une fonction PowerShell renvoie tous les objets qu'elle a produits en interne, même sans return explicite. Si vous appelez sans les récupérer des commandes ou des méthodes qui renvoient une valeur, comme New-Item ou .Append() de StringBuilder, cette valeur de retour s'écoule dans le flux de succès et arrive jusqu'à l'appelant. À l'inverse, une méthode dont le retour est void, comme .Add() de List[T], ne produit aucune sortie et ne nécessite donc aucune suppression. La solution consiste à jeter la sortie inutile avec $null = ..., à ajouter | Out-Null, ou à caster avec [void]. Du point de vue des performances, $null = ... est l'écriture la plus légère.
- Je veux pouvoir activer ou désactiver la journalisation détaillée d'un script au moment de l'exécution.
- Écrivez la progression du traitement avec Write-Verbose et ajoutez [CmdletBinding()] à la fonction. Cela suffit pour que l'affichage ne se déclenche que lorsque l'appelant précise -Verbose. Si vous voulez qu'il s'affiche en permanence, définissez $VerbosePreference = 'Continue' en tête du script. De la même façon, Write-Debug se contrôle avec -Debug et Write-Warning avec -WarningAction, du côté de l'appelant. Plutôt que de créer votre propre variable de niveau de journalisation, vous transmettez mieux votre intention aux autres lecteurs en vous appuyant sur les mécanismes standard de PowerShell.
- Comment conserver dans un fichier l'intégralité de la sortie, y compris les journaux détaillés et les avertissements ?
- Il existe trois approches selon l'usage. Pour simplement déverser tous les flux dans un fichier, redirigez avec *>. Pour conserver tel quel ce qui s'est affiché à l'écran, comme preuve d'exécution, Start-Transcript est la solution la plus simple. Si vous voulez pouvoir analyser cela par programme par la suite, il est plus sûr d'écrire une journalisation structurée en 1 ligne = 1 JSON via votre propre fonction de journalisation, et il vaut alors la peine de combiner cela avec une transcription, par sécurité.
- Peut-on conserver l'affichage de Write-Progress dans un fichier journal ?
- Non, ce n'est pas possible. L'affichage de progression est une fonctionnalité d'affichage de l'hôte, traitée séparément des flux de données que l'on peut rediriger. En exécution sans surveillance, il n'y a aucune destination d'affichage, donc considérez la progression comme distincte des informations à conserver dans un journal. En exécution sans surveillance, définir $ProgressPreference = 'SilentlyContinue' pour arrêter complètement l'affichage de progression peut, selon l'environnement, apporter un gain de vitesse visible. Si vous voulez conserver la progression dans un journal, il est plus pratique de n'écrire que des jalons avec Write-Verbose, comme « 50 sur 100 terminés ».
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.