Qual è la differenza tra “Write-Host”, “Write-Output” o “[console] :: WriteLine”?


194

Esistono diversi modi per emettere messaggi. Qual è la differenza effettiva tra l'output di qualcosa via Write-Host, Write-Outputo [console]::WriteLine?

Inoltre noto che se utilizzo:

write-host "count=" + $count

La +verrà incluso nell'output. Perché? L'espressione non dovrebbe essere valutata per produrre una singola stringa concatenata prima che venga scritta?


4
Write-Outputquando si emettono risultati. Write-Hostquando si emettono informazioni di registrazione. Non utilizzare mai [console]::writeline().
JohnL

2
@JohnL perché non dovremmo mai usare [console] :: writeline ()?
David Klempfner,

3
@Backwards_Dave Perché hai Write-Host .... Ok, potrei aver avuto l'impressione che mostrasse una nuova finestra della console (era molto tempo fa). Ciò non accade, ma resta il fatto che non è il linguaggio di PowerShell e non c'è niente che tu possa fare con [console]::writeline("hello world")cui non puoi fare Write-Host "hello world". Un'altra risposta migliore, più recente applicabile è quella che write-hostavvolge in write-informationmodo che i suoi dati vengano inseriti in un flusso in write-errormodo da poterli acquisire e utilizzarli altrove. [console]::writeline()non lo fa
JohnL

Risposte:


269

Write-Outputdovrebbe essere usato quando si desidera inviare dati nella linea di tubazioni, ma non si desidera necessariamente visualizzarli sullo schermo. La pipeline alla fine lo scriverà out-defaultse nient'altro lo utilizza per primo.

Write-Host dovrebbe essere usato quando vuoi fare il contrario.

[console]::WriteLineè essenzialmente ciò che Write-Hoststa facendo dietro le quinte.

Esegui questo codice dimostrativo ed esamina il risultato.

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 

È necessario racchiudere l'operazione di concatenazione tra parentesi, in modo che PowerShell elabori la concatenazione prima di tokenizzare l'elenco dei parametri Write-Hosto utilizzare l'interpolazione di stringhe

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

A proposito, guarda questo video di Jeffrey Snover che spiega come funziona la pipeline. Quando ho iniziato a studiare PowerShell ho scoperto che questa era la spiegazione più utile di come funziona la pipeline.


In Azure WebJob [console] :: WriteLine funziona ma Write-Host genererà un errore: L'errore interno Win32 "L'handle non è valido" si è verificato 0x6 durante l'impostazione degli attributi di carattere per il buffer di output della console. Non chiedermi perché.
Gil Roitto,

Correggimi se sbaglio, ma credo Write-Outputsia l'impostazione predefinita, ad esempio se hai uno PsObject e lo sputi sullo schermo facendo questo $object, in realtà farà la stessa cosa Write-Output $object. Potrebbe valere la pena ricordare
Kolob Canyon,

1
C'è una nuova guida: evitare l'uso Write-Outputquando possibile. Vedi github.com/PoshCode/PowerShellPracticeAndStyle/issues/… > Usa return solo per terminare l'esecuzione. > Evita output di scrittura (...). Invece, quando si desidera rendere più chiaro l'output, assegnare semplicemente l'output a una variabile denominata in modo pertinente. e metti quella variabile su una linea da sola per segnalare un output esplicito. > Write-Output -NoEnumerate è interrotto su PowerShell 6 ed è stato per 16 mesi o più - non c'è alcun piano per risolverlo. In sintesi:> NON USARE Output-Output - MAI.
Jeroen Wiert Pluimers,

28

A parte ciò che ha detto Andy, c'è un'altra differenza che potrebbe essere importante: write-host scrive direttamente sull'host e non restituisce nulla, il che significa che non è possibile reindirizzare l'output, ad esempio, su un file.

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

Ora esegui in PowerShell:

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

Come visto, non puoi reindirizzarli in un file. Questo forse sorprende per qualcuno che non sta attento.

Ma se si passa invece a utilizzare l'output di scrittura, il reindirizzamento funzionerà come previsto.


È possibile acquisire l'output di Write-Host se si utilizza Start-Process Powershell. \ A.ps1 -RedirectStandardOutput somefile.txt Tuttavia, ci sono problemi con la codifica (il file sarà in SystemDefaultEncoding).
MKesper,

16

Ecco un altro modo per ottenere l'equivalente di Write-Output. Inserisci la stringa tra virgolette:

"count=$count"

Puoi assicurarti che funzioni allo stesso modo di Write-Output eseguendo questo esperimento:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

I primi due produrranno "blah blah" su out.txt, ma il terzo no.

"help Write-Output" fornisce un suggerimento per questo comportamento:

Questo cmdlet viene in genere utilizzato negli script per visualizzare stringhe e altri oggetti sulla console. Tuttavia, poiché il comportamento predefinito è visualizzare gli oggetti alla fine di una pipeline, in genere non è necessario utilizzare il cmdlet.

In questo caso, la stringa stessa "count = $ count" è l'oggetto alla fine di una pipeline e viene visualizzata.


6

Per gli usi di Write-Host, PSScriptAnalyzerproduce la seguente diagnostica:

Evita di utilizzarlo Write-Hostperché potrebbe non funzionare in tutti gli host, non funziona in assenza di host e (prima di PS 5.0) non può essere soppresso, acquisito o reindirizzato. Invece, l'uso Write-Output, Write-Verboseo Write-Information.

Vedi la documentazione dietro quella regola per maggiori informazioni. Estratti per i posteri:

L'uso di Write-Hostè fortemente scoraggiato se non nell'uso dei comandi con il Showverbo. Il Showverbo significa esplicitamente "mostra sullo schermo, senza altre possibilità".

I comandi con il Showverbo non hanno questo controllo applicato.

Jeffrey Snover ha un post sul blog Write-Host considerato dannoso in cui afferma che Write-Host è quasi sempre la cosa sbagliata da fare perché interferisce con l'automazione e fornisce ulteriori spiegazioni dietro la diagnostica, tuttavia quanto sopra è un buon riassunto.


3

Dal mio test Write-Output e [Console] :: WriteLine () hanno prestazioni molto migliori di Write-Host.

A seconda della quantità di testo che devi scrivere, questo può essere importante.

Di seguito se il risultato di 5 test ciascuno per Write-Host, Write-Output e [Console] :: WriteLine ().

Nella mia esperienza limitata, ho scoperto che lavorando con qualsiasi tipo di dati del mondo reale ho bisogno di abbandonare i cmdlet e andare dritto per i comandi di livello inferiore per ottenere prestazioni decenti dai miei script.

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

1
Write-Outpute Write-Hostservono a scopi diversi, quindi non ha senso confrontare le loro prestazioni. Sì, l'uso diretto dei tipi .NET e dei relativi metodi è più rapido, ma perdi le funzionalità di livello superiore che i cmdlet di PowerShell possono fornire. [Console]::WriteLine()è simile al Write-Hostcaso attuale, ma non funzionerà in tutte le circostanze, perché non tutti gli host PowerShell sono console .
mklement0

0

Per quanto riguarda [Console] :: WriteLine (), è necessario utilizzarlo se si intende utilizzare pipeline in CMD (non in PowerShell). Supponiamo che tu voglia che la tua ps1 trasmetta molti dati allo stdout e che qualche altra utility li consumi / trasformi. Se usi Write-Host nello script sarà molto più lento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.