web-dev-qa-db-fra.com

Que dois-je utiliser: "Write-Host", "Write-Output" ou "[console] :: WriteLine"?

J'essaie de maîtriser PowerShell. Une chose simple que je peine à comprendre, c'est qu'il semble y avoir un certain nombre de façons différentes d'envoyer des messages. Que dois-je utiliser et quelle est la différence et existe-t-il un moyen conventionnel de le faire?

Je remarque aussi que si j'utilise:

write-Host "count=" + $count

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

177
Scott Langham

Write-Output doit être utilisé lorsque vous souhaitez envoyer des données dans la ligne de conduite, mais que vous ne voulez 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 en coulisse.

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 devez placer l'opération de concaténation entre parenthèses afin que PowerShell traite la concaténation avant de marquer la liste de paramètres pour Write-Host.

write-Host ("count=" + $count)

BTW - Regardez cette vidéo de Jeffrey Snover expliquant le fonctionnement du pipeline. À l'époque où j'ai commencé à apprendre PowerShell, je trouvais que c'était l'explication la plus utile du fonctionnement du pipeline.

247
Andy Arismendi

Outre ce que Andy a mentionné, une autre différence 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, lancez PowerShell:

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

Comme on le voit, vous ne pouvez pas les rediriger dans un fichier. C'est peut-être surprenant pour quelqu'un qui ne fait pas attention. 

Mais si vous utilisez à la place l'écriture en sortie, la redirection fonctionnera comme prévu.

28
KFL

Voici un autre moyen 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 exécutant ce test:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

Les deux premiers produiront "bla bla" dans out.txt, mais pas le troisième.

"help Write-Output" donne un indice de ce comportement:

Cette cmdlet est généralement utilisée dans les scripts pour afficher des chaînes et autres objets sur la console. Cependant, parce que le comportement par défaut est to afficher les objets à la fin d'un pipeline, ce n'est généralement pas nécessaire d'utiliser l'applet de commande.

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

14
FarmerBob

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

En fonction de la quantité de texte que vous devez écrire, cela peut être important.

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

Dans mon expérience limitée, j'ai constaté que lorsque je travaillais avec des données du monde réel, je devais abandonner les applets de commande et aller directement aux commandes de niveau inférieur pour obtenir des performances décentes dans 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
3
tom

Pour les utilisations de Write-Host, PSScriptAnalyzer génère le diagnostic suivant:

Évitez d'utiliser Write-Host car il pourrait ne pas fonctionner sur 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é. Utilisez plutôt 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 si vous utilisez des commandes avec le verbe Show. Le verbe Show signifie explicitement "montrer à l'écran, sans autre possibilité".

Les commandes avec le verbe Show n'ont pas cette vérification appliquée.

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

1
Drew Noakes

Concernant [Console] :: WriteLine () - vous devriez l’utiliser si vous voulez utiliser des pipelines dans CMD (pas dans Powershell). Supposons que votre ps1 diffuse de nombreuses données sur stdout, et qu'un autre utilitaire les consomme/les transforme. Si vous utilisez Write-Host dans le script, le processus sera beaucoup plus lent.

0
Mike Twc