Was soll ich verwenden: “Write-Host”, “Write-Output” oder ” :: WriteLine”?

Ich versuche, PowerShell in den Griff zu bekommen. Eine einfache Sache, die ich mühsam zu erarbeiten bin, ist, dass es eine Reihe von verschiedenen Möglichkeiten gibt, Nachrichten auszugeben. Was sollte ich verwenden und was ist der Unterschied, und gibt es einen konventionellen Weg?

Ich bemerke auch, dass wenn ich folgendes benutze:

write-host "count=" + $count 

Das + wird in die Ausgabe einbezogen. Warum ist das? Sollte der Ausdruck nicht ausgewertet werden, um einen einzelnen verketteten String zu erzeugen, bevor er ausgeschrieben wird?

Write-Output sollte verwendet werden, wenn Daten in der Pipeline gesendet werden sollen, aber nicht unbedingt auf dem Bildschirm angezeigt werden sollen. Die Pipeline schreibt sie schließlich auf out-default wenn nichts anderes sie zuerst verwendet. Write-Host sollte verwendet werden, wenn Sie das Gegenteil tun möchten. [console]::WriteLine ist im Wesentlichen was Write-Host hinter den Kulissen tut.

Führen Sie diesen Democode aus und untersuchen Sie das Ergebnis.

 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 

Sie müssen die Verkettungsoperation in Klammern einschließen, damit PowerShell die Verkettung vor dem Token der Parameterliste für Write-Host .

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

BTW – Sehen Sie sich dieses Video von Jeffrey Snover an und erklären Sie, wie die Pipeline funktioniert. Als ich anfing, PowerShell zu lernen, fand ich, dass dies die nützlichste Erklärung dafür ist, wie die Pipeline funktioniert.

Abgesehen von dem, was Andy erwähnt hat, gibt es einen weiteren Unterschied, der wichtig sein könnte – write-host schreibt direkt in den Host und gibt nichts zurück, was bedeutet, dass Sie die Ausgabe nicht z. B. in eine Datei redirect können.

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

Jetzt in PowerShell ausführen:

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

Wie Sie gesehen haben, können Sie sie nicht in eine Datei redirect. Das ist vielleicht überraschend für jemanden, der nicht vorsichtig ist.

Wenn Sie stattdessen stattdessen die Schreibausgabe verwenden, funktioniert die Umleitung wie erwartet.

Hier ist ein anderer Weg, um das Äquivalent von Write-Output zu erreichen. Setzen Sie Ihre Zeichenkette in Anführungszeichen:

 "count=$count" 

Sie können sicherstellen, dass dies beim Ausführen dieses Tests genauso funktioniert wie beim Schreiben:

 "blah blah" > out.txt Write-Output "blah blah" > out.txt Write-Host "blah blah" > out.txt 

Die ersten beiden werden “blah blah” nach out.txt ausgeben, aber die dritte nicht.

“help Write-Output” gibt einen Hinweis auf dieses Verhalten:

Dieses Cmdlet wird normalerweise in Skripts zum Anzeigen von Zeichenfolgen und anderen Objekten auf der Konsole verwendet. Da das Standardverhalten jedoch darin besteht, die Objekte am Ende einer Pipeline anzuzeigen, ist es in der Regel nicht erforderlich, das Cmdlet zu verwenden.

In diesem Fall ist der String selbst “count = $ count” das Objekt am Ende einer Pipeline und wird angezeigt.

Von meinen Tests führen Write-Output und [Console] :: WriteLine () viel besser aus als Write-Host.

Abhängig davon, wie viel Text Sie ausschreiben müssen, kann dies wichtig sein.

Unten, wenn das Ergebnis von 5 Tests für Write-Host, Write-Output und [Console] :: WriteLine () ist.

In meiner begrenzten Erfahrung habe ich festgestellt, dass ich bei der Arbeit mit Daten aus der realen Welt die Cmdlets verlassen muss und direkt auf die Befehle der unteren Ebene zugreifen muss, um meine Skripte anständig zu nutzen.

 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