“Write-Host”, “Write-Output” veya “[console] :: WriteLine” arasındaki fark nedir?


193

İleti çıkışının birkaç farklı yolu vardır. Yoluyla bir şeyler çıkışı arasında etkili fark nedir Write-Host, Write-Outputya [console]::WriteLine?

Ayrıca şunu kullanırsam:

write-host "count=" + $count

+Çıktıda dahil olur. Nedenmiş? İfade, yazılmadan önce tek bir sıralı dize üretecek şekilde değerlendirilmemeli mi?


4
Write-Outputsonuç verirken. Write-Hostgünlük bilgileri yayınlarken. Asla kullanmayın [console]::writeline().
JohnL

2
@JohnL neden asla [console] :: writeline () kullanmamalıyız?
David Klempfner

3
@Backwards_Dave Write-Host'a sahip olduğunuz için .... Tamam, yeni bir konsol penceresi (oldukça uzun zaman önceydi) gösterdiğine dair bir izlenim altında olabilirim. Bu gerçekleşmez, ancak gerçek şu ki bu powershell deyimi değildir ve [console]::writeline("hello world")yapamayacağınız bir şey yoktur Write-Host "hello world". Başka, daha iyi, daha yakın zamanda uygulanabilir cevap olmasıdır write-hostsargıları write-informationverileri gibi, dere üzerine koymak alır böylece write-errorbunu yakalamak ve başka yerlerde kullanabilirsiniz böylece. [console]::writeline()bunu yapmaz
JohnL

Yanıtlar:


268

Write-Outputboru hattında veri göndermek istediğinizde kullanılmalıdır, ancak mutlaka ekranda görüntülemek istemezsiniz. İlk olarak out-defaultbaşka hiçbir şey kullanmazsa, boru hattı sonunda bunu yazacaktır .

Write-Host tam tersini yapmak istediğinizde kullanılmalıdır.

[console]::WriteLineaslında Write-Hostperde arkasında neler yapıyor.

Bu tanıtım kodunu çalıştırın ve sonucu inceleyin.

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 

Birleştirme işlemini parantez içine almanız gerekir, böylece PowerShell, parametre listesini belirtmeden önce bitiştirmeyi işler Write-Hostveya dize enterpolasyonunu kullanır

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

BTW - Jeffrey Snover'ın boru hattının nasıl çalıştığını açıklayan bu videosunu izleyin . PowerShell öğrenmeye başladığımda bunu boru hattının nasıl çalıştığına dair en yararlı açıklama olarak buldum.


Azure WebJob'da [console] :: WriteLine çalışır ancak Write-Host hataya neden olur: Konsol çıktı arabelleği için karakter öznitelikleri ayarlanırken Win32 dahili hatası "Tanıtıcı geçersiz" 0x6 oluştu. Bana nedenini sorma.
Gil Roitto

Yanılıyorsam beni düzeltin, ancak Write-Outputvarsayılan olduğuna inanıyorum , örneğin bir PsObject'iniz varsa ve bunu yaparak ekrana tükürdüğünüzde $objectaslında bununla aynı şeyi yapar Write-Output $object. Bahsetmeye değer olabilir
Kolob Canyon

1
Yeni bir kılavuz var: Write-Outputmümkün olduğunda kullanmaktan kaçının . Bkz. Github.com/PoshCode/PowerShellPracticeAndStyle/issues/… > Dönüşü yalnızca yürütmeyi sonlandırmak için kullanın. > Yazma Çıkışından Kaçının (...). Bunun yerine, çıktıyı daha net hale getirmek istediğinizde, çıktıyı ilgili olarak adlandırılmış bir değişkene atamanız yeterlidir. ve açık bir çıktıyı belirtmek için bir değişkeni tek başına bir satıra koyun. > Write-Output -NoEnumerate, PowerShell 6'da bozuldu ve 16 ay veya daha uzun süredir düzeltildi. Özetle:> Write-Output - EVER KULLANMAYIN.
Jeroen Wiert Pluimers

28

Andy'nin bahsettikleri dışında, önemli olabilecek başka bir fark daha var - yazma-ana bilgisayarı doğrudan ana bilgisayara yazar ve hiçbir şey döndürmez, yani çıktıyı, örneğin bir dosyaya yönlendiremezsiniz.

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

Şimdi PowerShell'de çalıştırın:

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

Görüldüğü gibi, onları bir dosyaya yönlendiremezsiniz. Dikkatli olmayan biri için bu şaşırtıcı olabilir.

Ancak bunun yerine yazma çıktısını kullanmaya geçiş yapıldıysa, yeniden yönlendirme beklendiği gibi çalışır.


Start-Process Powershell'i kullanırsanız Write-Host Çıktısını yakalamanız mümkündür. \ A.ps1 -RedirectStandardOutput somefile.txt Ancak kodlamada sorun var (dosya SystemDefaultEncoding içinde olacak).
MKesper

16

İşte Write-Output eşdeğerini başarmanın başka bir yolu. Dizenizi tırnak içine alın:

"count=$count"

Bu denemeyi çalıştırarak Yazma-Çıktı ile aynı şekilde çalıştığından emin olabilirsiniz:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

İlk ikisi out.txt'ye "falan filan" çıktısı verir, ama üçüncüsü çıkmaz.

"help Write-Output" bu davranışın bir ipucunu verir:

Bu cmdlet genellikle komut dosyalarında konsoldaki dizeleri ve diğer nesneleri görüntülemek için kullanılır. Ancak, varsayılan davranış bir boru hattının sonunda nesneleri görüntülemek olduğundan, genellikle cmdlet'in kullanılması gerekmez.

Bu durumda, dizenin kendisi "count = $ count" bir ardışık düzenin sonundaki nesnedir ve görüntülenir.


6

Kullanımları için Write-Host, PSScriptAnalyzeraşağıdaki tanılama üretir:

Kullanmaktan kaçının Write-Hostçünkü tüm ana bilgisayarlarda çalışmayabilir, ana bilgisayar olmadığında çalışmaz ve (PS 5.0'dan önce) bastırılamaz, yakalanamaz veya yönlendirilemez. Bunun yerine, kullanımı Write-Output, Write-Verboseya da Write-Information.

Daha fazla bilgi için bu kuralın arkasındaki belgelere bakın . Gelecek nesiller için alıntılar:

Kullanımı Write-Hostbüyük ölçüde birlikte komutların kullanımında sürece önerilmez Showfiil. ShowFiil açıkça "hayır diğer olasılıklar ekranda göstermek," anlamına gelir.

ShowFiil içeren komutlara bu denetim uygulanmaz.

Jeffrey Snover'ın bir blog yazısı var Write-Host Sayılan Zararlı Yazma Host'un otomasyona müdahale ettiği ve teşhisin arkasında daha fazla açıklama sağladığı için neredeyse her zaman yanlış bir şey olduğunu iddia ediyor , ancak yukarıdaki iyi bir özet.


3

Testlerimden Write-Output ve [Console] :: WriteLine (), Write-Host'dan çok daha iyi performans gösterir.

Ne kadar metin yazmanız gerektiğine bağlı olarak bu önemli olabilir.

Aşağıda her biri Write-Host, Write-Output ve [Console] :: WriteLine () için 5 testin sonucu varsa.

Sınırlı tecrübemde, cmdlet'leri terk etmem ve komut dosyalarımdan iyi bir performans elde etmek için daha düşük seviyeli komutlar için gitmem gereken her türlü gerçek dünya verileriyle çalışırken buldum.

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-Outputve Write-Hostfarklı amaçlara hizmet ediyorlar, bu yüzden performanslarını karşılaştırmanın bir anlamı yok. Evet, .NET türlerinin ve yöntemlerinin doğrudan kullanımı daha hızlıdır, ancak PowerShell cmdlet'lerinin sağlayabileceği üst düzey özellikleri kaçırırsınız. eldeki durumda [Console]::WriteLine()benzer Write-Host, ancak tüm koşullarda çalışmaz, çünkü tüm PowerShell ana bilgisayarları konsol değildir .
mklement0

0

[Console] :: WriteLine () ile ilgili olarak - CMD'de boru hatları kullanacaksanız (powershell'de değil) kullanmalısınız. Ps1'inizin stdout'a çok fazla veri akışını ve onu tüketmek / dönüştürmek için başka bir yardımcı program olmasını istediğinizi varsayalım. Senaryoda Write-Host kullanırsanız, çok daha yavaş olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.