2012-01-06 20 views
150

Sto provando a fare i conti con PowerShell. Una cosa semplice che sto cercando di risolvere è che sembrano esserci diversi modi per emettere messaggi. Quale dovrei usare e qual è la differenza, e c'è un modo convenzionale per farlo?Quale dovrei usare: "Write-Host", "Write-Output" o "[console] :: WriteLine"?

Ho anche notato che se uso:

write-host "count=" + $count 

Il + verrà incluso nell'output. Perché? Non si deve valutare l'espressione per produrre una singola stringa concatenata prima che venga scritta?

+3

'Write-Output' quando si emettono risultati. 'Write-Host' quando stai emettendo informazioni di registrazione. Non usare mai '[console] :: writeline()'. – JohnL

+1

@JohnL perché non dovremmo mai usare [console] :: writeline()? –

+3

@Backwards_Dave Perché hai un host di scrittura .... Ok, potrei avere avuto qualche impressione che mostrasse una nuova finestra della console (era molto tempo fa). Ciò non accade, ma resta il fatto che non è l'idioma di PowerShell e non c'è niente che puoi fare con '[console] :: writeline (" ciao mondo ")' che non puoi fare con 'Write-Host" ciao mondo "'. Un'altra risposta migliore, più recente, è che 'write-host' esegue il wrapping' write-information' in modo che i suoi dati vengano messi in un flusso come 'write-error' in modo da poterlo acquisire e utilizzarlo altrove. '[console] :: writeline()' non lo fa – JohnL

risposta

219

Write-Output deve essere utilizzato quando si desidera inviare dati nella linea del tubo, ma non necessariamente per visualizzarlo sullo schermo. La pipeline lo scriverà a out-default se non lo usa prima. Write-Host dovrebbe essere usato quando si vuole fare il contrario. [console]::WriteLine è essenzialmente ciò che sta facendo Write-Host dietro le quinte.

Eseguire questo codice dimostrativo ed esaminare 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 

Avrai bisogno di racchiudere l'operazione di concatenazione tra parentesi in modo che che PowerShell elabora la concatenazione prima di creazione di token l'elenco di parametri per Write-Host.

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

BTW - Guarda questo video di Jeffrey Snover spiegare come funziona il gasdotto. Quando ho iniziato a imparare PowerShell ho scoperto che questa è la spiegazione più utile di come funziona la pipeline.

+5

+1 per il collegamento video, roba buona! – D3vtr0n

+0

Un altro +1 per il link suggerito, sicuramente un ottimo e utile colloquio tra esperti – fra

+0

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

24

Oltre a ciò che ha menzionato Andy, c'è un'altra differenza che potrebbe essere importante: l'host di scrittura scrive direttamente nell'host e non restituisce nulla, ovvero non è possibile reindirizzare l'output, ad esempio in un file.

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

Ora gestiscono in PowerShell:

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

Come si è visto, non si possono reindirizzare in un file. Questo forse sorprende per qualcuno che non sta attento.

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

+0

È possibile acquisire l'output di scrittura-host se si utilizza il potere di avvio di Start-Process. \ A.ps1 -RedirectStandardOutput somefile.txt C'è comunque un problema con la codifica (il file sarà in SystemDefaultEncoding). – MKesper

11

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

"count=$count" 

È possibile assicurarsi che questo funziona come Write-Output eseguendo questo esperimento:

"blah blah" > out.txt 

Write-Output "blah blah" > out.txt 

Write-Host "blah blah" > out.txt 

Le prime due di uscita volontà "bla bla" per uscire. txt, ma il terzo no.

"aiuto Write-Output" dà un suggerimento di questo comportamento:

This cmdlet is typically used in scripts to display strings and other objects on the console. However, because the default behavior is to display the objects at the end of a pipeline, it is generally not necessary to use the cmdlet.

In questo caso, la stringa stessa "count = count $" è l'oggetto al termine di una condotta, e viene visualizzato .

3

Dalla mia prova Write-Output e [Console] :: WriteLine() funzionano molto meglio di Write-Host.

A seconda della quantità di testo che è necessario scrivere, potrebbe essere importante.

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

Nella mia esperienza limitata, ho trovato quando lavoro con qualsiasi tipo di dati del mondo reale, ho bisogno di abbandonare i cmdlet e andare direttamente ai 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