¿Qué debo usar: "Write-Host", "Write-Output", o "[console]::WriteLine"?


Estoy tratando de familiarizarme con PowerShell. Una cosa simple que estoy luchando para resolver es que parece haber un número de diferentes maneras de salida de mensajes. ¿Qué debo usar y cuál es la diferencia, y hay una forma convencional de hacerlo?

También noto que si uso:

write-host "count=" + $count

El + se incluye en la salida. ¿Por qué es eso? ¿No debería evaluarse la expresión para producir una sola cadena concatenada antes de que se escriba?

 167
Author: Peter Mortensen, 2012-01-06

4 answers

Write-Output se debe utilizar cuando se desea enviar datos en la línea de tubería, pero no necesariamente quiere mostrarlo en la pantalla. La canalización eventualmente lo escribirá en out-default si nada más lo usa primero. Write-Host se debe usar cuando se quiere hacer lo contrario. [console]::WriteLine es esencialmente lo que Write-Host está haciendo detrás de escena.

Ejecute este código de demostración y examine el resultado.

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 

Deberá incluir la operación de concatenación entre paréntesis para que PowerShell procesa la concatenación antes de tokenizar la lista de parámetros para Write-Host.

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

POR cierto - Mira este video de Jeffrey Snover explicando cómo funciona el pipeline. Cuando empecé a aprender PowerShell, encontré que esta era la explicación más útil de cómo funciona la canalización.

 234
Author: Andy Arismendi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-31 10:21:00

Aparte de lo que Andy mencionó, hay otra diferencia que podría ser importante: write - host escribe directamente al host y no devuelve nada, lo que significa que no puede redirigir la salida, por ejemplo, a un archivo.

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

Ahora se ejecuta en PowerShell:

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

Como se ha visto, no puede redirigirlos a un archivo. Esto puede ser sorprendente para alguien que no tiene cuidado.

Pero si se cambia a usar write-output en su lugar, obtendrá la redirección funcionando como se espera.

 26
Author: KFL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-23 01:02:44

Aquí hay otra forma de lograr el equivalente de Write-Output. Simplemente ponga su cadena entre comillas:

"count=$count"

Puede asegurarse de que esto funcione igual que Write-Output ejecutando este experimento:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

Los dos primeros saldrán "bla bla" a la salida.txt, pero el tercero no.

"help Write-Output" da una pista de este comportamiento:

Este cmdlet se utiliza normalmente en scripts para mostrar cadenas y otros objetos en la consola. Sin embargo, porque el el comportamiento predeterminado es mostrar los objetos al final de una canalización, generalmente no es necesario para usar el cmdlet.

En este caso, la cadena misma "count=count count" es el objeto al final de una canalización, y se muestra.

 14
Author: FarmerBob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-07 19:09:38

Desde mis pruebas Write-Output y [Console]:: WriteLine() funcionan mucho mejor que Write-Host.

Dependiendo de la cantidad de texto que necesite escribir, esto puede ser importante.

A continuación si el resultado de 5 pruebas cada uno para Write-Host, Write-Output y [Console]::WriteLine().

En mi experiencia limitada, he encontrado que cuando trabajo con cualquier tipo de datos del mundo real necesito abandonar los cmdlets e ir directamente a los comandos de nivel inferior para obtener un rendimiento decente de mi guiones.

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
Author: tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-15 08:31:13