213 votes

Quelle est la différence entre "Write-Host", "Write-Output", ou "[console]::WriteLine" ?

Il existe un certain nombre de façons différentes d'émettre des messages. Quelle est la différence effective entre l'envoi d'un message par le biais de Write-Host , Write-Output ou [console]::WriteLine ?

Je remarque aussi que si j'utilise :

write-host "count=" + $count

Le site + est inclus dans la sortie. Pourquoi cela ? L'expression ne devrait-elle pas être évaluée pour produire une seule chaîne concaténée avant d'être écrite ?

5 votes

Write-Output quand vous émettez des résultats. Write-Host lorsque vous émettez des informations de journalisation. N'utilisez jamais [console]::writeline() .

3 votes

@JohnL pourquoi ne devrions-nous jamais utiliser [console]::writeline() ?

4 votes

@Backwards_Dave Parce que vous avez Write-Host.... Ok, j'ai peut-être eu l'impression que cela montrait une nouvelle fenêtre de console (c'était il y a assez longtemps). Cela n'arrive pas, mais le fait est que ce n'est pas l'idiome powershell et qu'il n'y a rien que vous puissiez faire avec... [console]::writeline("hello world") que vous ne pouvez pas faire avec Write-Host "hello world" . Une autre réponse, meilleure et plus récente, est que write-host enveloppes write-information donc ses données sont placées dans un flux comme write-error pour que vous puissiez le capturer et l'utiliser ailleurs. [console]::writeline() ne le fait pas

295voto

Andy Arismendi Points 16501

Write-Output doit être utilisé lorsque vous souhaitez envoyer des données dans le pipe-line, mais pas nécessairement les afficher à l'écran. Le pipeline finira par l'écrire dans out-default si rien d'autre ne l'utilise en premier.

Write-Host doit être utilisé lorsque vous voulez faire le contraire.

[console]::WriteLine est essentiellement ce que Write-Host fait dans les coulisses.

Exécutez ce code de démonstration et examinez le résultat.

function Test-Output {
    Write-Output "Hello World"
}

function Test-Output2 {
    Write-Host "Hello World" -foreground Green
}

function Receive-Output {
    process { Write-Host $_ -foreground Yellow }
}

#Output piped to another function, not displayed in first.
Test-Output | Receive-Output

#Output not piped to 2nd function, only displayed in first.
Test-Output2 | Receive-Output 

#Pipeline sends to Out-Default at the end.
Test-Output 

Vous devrez mettre l'opération de concaténation entre parenthèses, afin que PowerShell traite la concaténation avant de tokeniser la liste des paramètres pour l'opération Write-Host ou utiliser l'interpolation de chaînes de caractères

write-host ("count=" + $count)
# or
write-host "count=$count"

BTW - Regardez ceci vidéo de Jeffrey Snover expliquant le fonctionnement du pipeline. Lorsque j'ai commencé à apprendre PowerShell, j'ai trouvé que c'était l'explication la plus utile du fonctionnement du pipeline.

0 votes

Dans un Azure WebJob, [console]::WriteLine fonctionne mais Write-Host entraîne une erreur : L'erreur interne Win32 "The handle is invalid" 0x6 s'est produite lors de la définition des attributs de caractères pour le tampon de sortie de la console. Ne me demandez pas pourquoi.

0 votes

Corrigez-moi si je me trompe, mais je crois que Write-Output est la valeur par défaut. Par exemple, si vous avez un PsObject et que vous l'affichez à l'écran en faisant ceci $object cela fera la même chose que ceci Write-Output $object . Cela vaut peut-être la peine de mentionner

2 votes

Il existe de nouvelles directives : évitez d'utiliser Write-Output lorsque cela est possible. Voir github.com/PoshCode/PowerShellPracticeAndStyle/issues/ > Utiliser le retour uniquement pour terminer l'exécution. > Éviter l'écriture-sortie (...). Au lieu de cela, lorsque vous voulez rendre la sortie plus claire, il suffit d'assigner la sortie à une variable nommée de manière appropriée et de placer cette variable sur une ligne à part pour signaler une sortie explicite. > Write-Output -NoEnumerate est cassé dans PowerShell 6 et l'est depuis 16 mois ou plus -- il n'y a aucun plan pour le réparer. En résumé : > NE PAS UTILISER Write-Output -- JAMAIS.

29voto

KFL Points 1082

En dehors de ce qu'Andy a mentionné, il y a une autre différence qui pourrait être importante - write-host écrit directement sur l'hôte et ne renvoie rien, ce qui signifie que vous ne pouvez pas rediriger la sortie, par exemple, vers un fichier.

---- script a.ps1 ----
write-host "hello"

Maintenant, exécutez dans PowerShell :

PS> .\a.ps1 > someFile.txt
hello
PS> type someFile.txt
PS>

Comme vu, vous ne pouvez pas les rediriger dans un fichier. Cela peut être surprenant pour quelqu'un qui ne fait pas attention.

Mais si vous changez pour utiliser write-output à la place, la redirection fonctionnera comme prévu.

0 votes

Il est possible de capturer la sortie Write-Host si vous utilisez Start-Process Powershell . \a.ps1 -RedirectStandardOutput somefile.txt Il y a un problème avec l'encodage, cependant (le fichier sera en SystemDefaultEncoding).

16voto

Leonid Tsybert Points 418

Voici une autre façon d'accomplir l'équivalent de Write-Output. Il suffit de mettre votre chaîne entre guillemets :

"count=$count"

Vous pouvez vous assurer que cela fonctionne de la même manière que Write-Output en effectuant cette expérience :

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

Les deux premiers afficheront "blah blah" dans out.txt, mais pas le troisième.

"Aide Write-Output" donne un aperçu de ce comportement :

Cette cmdlet est généralement utilisée dans les scripts pour afficher des chaînes et d'autres objets sur la console. objets sur la console. Toutefois, comme le comportement par défaut consiste à d'afficher les objets à la fin d'un pipeline, il n'est généralement pas nécessaire d'utiliser cette cmdlet.

Dans ce cas, la chaîne elle-même "count=$count" est l'objet à la fin d'un pipeline, et est affichée.

7voto

Drew Noakes Points 69288

Pour les usages de Write-Host , PSScriptAnalyzer produit le diagnostic suivant :

Évitez d'utiliser Write-Host car il peut ne pas fonctionner dans tous les hôtes, ne fonctionne pas lorsqu'il n'y a pas d'hôte, et (avant PS 5.0) ne peut pas être supprimé, capturé ou redirigé. À la place, utilisez Write-Output , Write-Verbose ou Write-Information .

Voir le documentation derrière cette règle pour plus d'informations. Extraits pour la postérité :

L'utilisation de Write-Host est fortement déconseillée, sauf dans l'utilisation de commandes avec l'attribut Show le verbe. Le site Show Le verbe signifie explicitement "montrer sur l'écran, sans autre possibilité".

Commandes avec le Show Le verbe n'a pas été vérifié.

Jeffrey Snover a publié un article de blog Write-Host considéré comme nuisible dans lequel il affirme Write-Host est presque toujours la mauvaise chose à faire car il interfère avec l'automatisation. et fournit plus d'explications sur le diagnostic, mais ce qui précède est un bon résumé.

3voto

tom Points 75

D'après mes essais, Write-Output et [Console]::WriteLine() fonctionnent beaucoup mieux que Write-Host.

Selon la quantité de texte que vous devez rédiger, cela peut être important.

Voici le résultat de 5 tests pour Write-Host, Write-Output et [Console]::WriteLine().

D'après mon expérience limitée, j'ai constaté que lorsque je travaille avec des données du monde réel, je dois abandonner les cmdlets et passer directement aux commandes de niveau inférieur pour obtenir des performances décentes de mes scripts.

measure-command {$count = 0; while ($count -lt 1000) { Write-Host "hello"; $count++ }}

1312ms
1651ms
1909ms
1685ms
1788ms

measure-command { $count = 0; while ($count -lt 1000) { Write-Output "hello"; $count++ }}

97ms
105ms
94ms
105ms
98ms

measure-command { $count = 0; while ($count -lt 1000) { [console]::WriteLine("hello"); $count++ }}

158ms
105ms
124ms
99ms
95ms

2 votes

Write-Output y Write-Host servent des objectifs différents, il est donc inutile de comparer leurs performances. Il est vrai que l'utilisation directe des types .NET et de leurs méthodes est plus rapide, mais vous perdez les fonctionnalités de plus haut niveau que les cmdlets PowerShell peuvent fournir. [Console]::WriteLine() s'apparente à Write-Host dans le cas présent, mais ne fonctionnera pas dans toutes les circonstances, car les hôtes PowerShell ne sont pas tous consoles .

Prograide.com

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

Powered by:

X