Apa perbedaan antara “Write-Host”, “Write-Output”, atau “[console] :: WriteLine”?

192

Ada sejumlah cara berbeda untuk menghasilkan pesan. Apa perbedaan efektif antara keluaran sesuatu melalui Write-Host, Write-Outputatau [console]::WriteLine?

Saya juga perhatikan bahwa jika saya menggunakan:

write-host "count=" + $count

Akan +dimasukkan dalam output. Kenapa begitu? Tidakkah ungkapan itu harus dievaluasi untuk menghasilkan satu string gabungan sebelum ditulis?

Scott Langham
sumber
4
Write-Outputketika Anda memancarkan hasil. Write-Hostketika Anda memancarkan informasi logging. Jangan pernah gunakan [console]::writeline().
JohnL
2
@ JohnL mengapa kita tidak pernah menggunakan [konsol] :: writeline ()?
David Klempfner
3
@Backwards_Dave Karena Anda memiliki Write-Host .... Ok, saya mungkin mendapat kesan bahwa itu menunjukkan jendela konsol baru (itu sudah lama sekali). Itu tidak terjadi, tetapi kenyataannya tetap bahwa itu bukan idiom PowerShell dan tidak ada yang dapat Anda lakukan dengan [console]::writeline("hello world")Anda tidak dapat melakukannya Write-Host "hello world". Jawaban lain yang lebih baik, lebih baru berlaku adalah yang write-hostmembungkus write-informationsehingga datanya dimasukkan ke aliran seperti write-errorsehingga Anda dapat menangkapnya dan menggunakannya di tempat lain. [console]::writeline()tidak melakukan itu
JohnL

Jawaban:

267

Write-Outputharus digunakan ketika Anda ingin mengirim data pada saluran pipa, tetapi tidak selalu ingin menampilkannya di layar. Pipa akhirnya akan menuliskannya out-defaultjika tidak ada orang lain yang menggunakannya terlebih dahulu.

Write-Host harus digunakan ketika Anda ingin melakukan yang sebaliknya.

[console]::WriteLinepada dasarnya adalah apa Write-Hostyang dilakukan di balik layar.

Jalankan kode demonstrasi ini dan periksa hasilnya.

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 

Anda harus melampirkan operasi penggabungan dalam tanda kurung, sehingga PowerShell memproses penggabungan sebelum tokenizing daftar parameter untuk Write-Host, atau menggunakan interpolasi string

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

BTW - Tonton video Jeffrey Snover ini menjelaskan cara kerja pipeline. Kembali ketika saya mulai belajar PowerShell saya menemukan ini menjadi penjelasan yang paling berguna tentang cara kerja pipeline.

Andy Arismendi
sumber
Dalam Azure WebJob [konsol] :: WriteLine berfungsi tetapi Write-Host akan menghasilkan kesalahan: Kesalahan internal Win32 "Pegangan tidak valid" 0x6 terjadi saat mengatur atribut karakter untuk buffer output konsol. Jangan tanya kenapa.
Gil Roitto
Koreksi saya jika saya salah, tetapi saya percaya Write-Outputadalah defaultnya misalnya jika Anda memiliki PsObject dan Anda hanya memuntahkannya ke layar dengan melakukan ini, $objectitu sebenarnya akan melakukan hal yang sama seperti ini Write-Output $object. Mungkin layak disebut
Kolob Canyon
1
Ada panduan baru: hindari penggunaan Write-Outputjika memungkinkan. Lihat github.com/PoshCode/PowerShellPracticeAndStyle/issues/… > Gunakan pengembalian hanya untuk mengakhiri eksekusi. > Hindari Write-Output (...). Sebagai gantinya, ketika Anda ingin membuat output lebih jelas, tetapkan saja output ke variabel bernama relevan. dan menempatkan variabel pada baris dengan sendirinya untuk menandakan output eksplisit. > Write-Output -NoEnumerate rusak di PowerShell 6 dan telah selama 16 bulan atau lebih - tidak ada rencana untuk memperbaikinya. Singkatnya:> JANGAN GUNAKAN Write-Output - EVER.
Jeroen Wiert Pluimers
28

Terlepas dari apa yang disebutkan Andy, ada perbedaan lain yang penting - write-host langsung menulis ke host dan tidak mengembalikan apa pun, artinya Anda tidak dapat mengarahkan ulang output, misalnya, ke file.

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

Sekarang jalankan di PowerShell:

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

Seperti yang terlihat, Anda tidak dapat mengarahkan mereka ke file. Ini mungkin mengejutkan bagi seseorang yang tidak berhati-hati.

Tetapi jika beralih menggunakan write-output sebagai gantinya, Anda akan mendapatkan pengalihan berfungsi seperti yang diharapkan.

KFL
sumber
Dimungkinkan untuk mengambil Output Write-Host jika Anda menggunakan Start-Process Powershell. \ A.ps1 -RedirectStandardOutput somefile.txt Namun ada masalah dengan pengodean (file akan berada di SystemDefaultEncoding).
MKesper
16

Berikut cara lain untuk mencapai yang setara dengan Write-Output. Masukkan saja string Anda ke dalam tanda kutip:

"count=$count"

Anda dapat memastikan ini bekerja sama dengan Write-Output dengan menjalankan percobaan ini:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

Dua yang pertama akan menampilkan "blah blah" ke out.txt, tetapi yang ketiga tidak.

"help Write-Output" memberikan petunjuk tentang perilaku ini:

Cmdlet ini biasanya digunakan dalam skrip untuk menampilkan string dan objek lain di konsol. Namun, karena perilaku default adalah untuk menampilkan objek di ujung pipa, umumnya tidak perlu menggunakan cmdlet.

Dalam kasus ini, string itu sendiri "count = $ count" adalah objek di akhir pipa, dan ditampilkan.

FarmerBob
sumber
6

Untuk penggunaan Write-Host, PSScriptAnalyzerbuat diagnostik berikut:

Hindari penggunaan Write-Hostkarena mungkin tidak bekerja di semua host, tidak berfungsi ketika tidak ada host, dan (sebelum PS 5.0) tidak dapat ditekan, ditangkap, atau dialihkan. Sebaliknya, penggunaan Write-Output, Write-Verboseatau Write-Information.

Lihat dokumentasi di balik aturan itu untuk informasi lebih lanjut. Kutipan untuk anak cucu:

Penggunaan Write-Hostsangat tidak dianjurkan kecuali dalam penggunaan perintah dengan Showkata kerja. Kata Showkerjanya secara eksplisit berarti "tampil di layar, tanpa kemungkinan lain".

Perintah dengan Showkata kerja tidak menerapkan pemeriksaan ini.

Jeffrey Snover memiliki posting blog Write-Host Dianggap Berbahaya di mana ia mengklaim Write-Host hampir selalu merupakan hal yang salah untuk dilakukan karena mengganggu otomatisasi dan memberikan lebih banyak penjelasan di balik diagnostik, namun di atas adalah ringkasan yang baik.

Drew Noakes
sumber
3

Dari pengujian saya Write-Output dan [Console] :: WriteLine () berkinerja lebih baik daripada Write-Host.

Tergantung pada seberapa banyak teks yang Anda butuhkan untuk menulis ini mungkin penting.

Di bawah ini jika hasil masing-masing dari 5 tes untuk Write-Host, Write-Output dan [Console] :: WriteLine ().

Dalam pengalaman saya yang terbatas, saya telah menemukan ketika bekerja dengan segala jenis data dunia nyata saya harus meninggalkan cmdlet dan langsung menuju perintah tingkat yang lebih rendah untuk mendapatkan kinerja yang layak dari skrip saya.

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
tom
sumber
1
Write-Outputdan Write-Hostmelayani tujuan yang berbeda, sehingga tidak ada gunanya membandingkan kinerja mereka. Ya, penggunaan langsung tipe .NET dan metodenya lebih cepat, tetapi Anda kehilangan fitur tingkat tinggi yang dapat disediakan PowerShell cmdlet. [Console]::WriteLine()mirip Write-Hostdalam kasus yang dihadapi, tetapi tidak akan berfungsi dalam semua keadaan, karena tidak semua host PowerShell adalah konsol .
mklement0
0

Mengenai [Konsol] :: WriteLine () - Anda harus menggunakannya jika Anda akan menggunakan saluran pipa di CMD (bukan di powershell). Katakanlah Anda ingin ps1 Anda untuk mengalirkan banyak data ke stdout, dan beberapa utilitas lain untuk mengkonsumsi / mengubahnya. Jika Anda menggunakan Write-Host dalam skrip, itu akan jauh lebih lambat.

Mike Twc
sumber