Có gì khác biệt giữa các dòng Viết-Máy chủ, Viết Viết-Đầu ra, hoặc [[bảng điều khiển] :: WriteLine Lần?


192

Có một số cách khác nhau để xuất thông điệp. Sự khác biệt hiệu quả giữa xuất ra một cái gì đó qua là gì Write-Host, Write-Outputhay [console]::WriteLine?

Tôi cũng nhận thấy rằng nếu tôi sử dụng:

write-host "count=" + $count

Được +bao gồm trong đầu ra. Tại sao vậy Không nên đánh giá biểu thức để tạo ra một chuỗi nối đơn trước khi nó được viết ra?


4
Write-Outputkhi bạn đang phát ra kết quả. Write-Hostkhi bạn đang phát thông tin đăng nhập. Không bao giờ sử dụng [console]::writeline().
JohnL

2
@JohnL tại sao chúng ta không bao giờ nên sử dụng [console] :: writeline ()?
David Klempfner

3
@Backwards_Dave Bởi vì bạn có Write-Host .... Ok, tôi có thể đã bị ấn tượng rằng nó hiển thị một cửa sổ giao diện điều khiển mới (cách đây khá lâu). Điều đó không xảy ra, nhưng thực tế vẫn không phải là thành ngữ quyền hạn và bạn không thể làm gì với [console]::writeline("hello world")điều đó Write-Host "hello world". Một câu trả lời khác, tốt hơn, gần đây hơn có thể áp dụng là write-hostkết thúc tốt đẹp write-informationđể dữ liệu của nó được đưa vào một luồng như write-errorvậy để bạn có thể nắm bắt và sử dụng nó ở nơi khác. [console]::writeline()không làm điều đó
JohnL

Câu trả lời:


267

Write-Outputnên được sử dụng khi bạn muốn gửi dữ liệu trên đường ống, nhưng không nhất thiết muốn hiển thị nó trên màn hình. Đường ống cuối cùng sẽ ghi nó vào out-defaultnếu không có gì khác sử dụng nó trước.

Write-Host nên được sử dụng khi bạn muốn làm ngược lại.

[console]::WriteLinevề cơ bản là những gì Write-Hostđang làm đằng sau hậu trường.

Chạy mã trình diễn này và kiểm tra kết quả.

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 

Bạn sẽ cần phải bao gồm hoạt động nối trong ngoặc đơn để PowerShell xử lý phép nối trước khi mã hóa danh sách tham số cho Write-Hosthoặc sử dụng phép nội suy chuỗi

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

BTW - Xem video này của Jeffrey Snover giải thích cách thức hoạt động của đường ống. Quay lại khi tôi bắt đầu học PowerShell, tôi thấy đây là lời giải thích hữu ích nhất về cách thức hoạt động của đường ống.


Trong Azure WebJob [console] :: WriteLine hoạt động nhưng Write-Host sẽ gây ra lỗi: Lỗi nội bộ Win32 "Xử lý không hợp lệ" xảy ra 0x6 trong khi đặt thuộc tính ký tự cho bộ đệm đầu ra của bàn điều khiển. Đừng hỏi tôi tại sao.
Gil Roitto

Sửa lỗi cho tôi nếu tôi sai, nhưng tôi tin Write-Outputlà mặc định, ví dụ: nếu bạn có PsObject và bạn chỉ cần nhổ nó ra màn hình bằng cách làm điều này $objectthì nó thực sự sẽ làm điều tương tự như thế này Write-Output $object. Có thể đáng nói
Hẻm núi Kolob

1
Có hướng dẫn mới: tránh sử dụng Write-Outputkhi có thể. Xem github.com/PoshCode/PowerShellPracticeAndStyle/issues/iêu > Chỉ sử dụng trả về để kết thúc thực hiện. > Tránh ghi đầu ra (...). Thay vào đó, khi bạn muốn làm cho đầu ra rõ ràng hơn, chỉ cần gán đầu ra cho một biến có tên phù hợp. và tự đặt một biến đó trên một dòng để báo hiệu đầu ra rõ ràng. > Đầu ra ghi -Không bị hỏng trên PowerShell 6 và đã được 16 tháng hoặc lâu hơn - không có kế hoạch khắc phục. Tóm lại:> KHÔNG SỬ DỤNG Đầu ra ghi - EVER.
Jeroen Wiert Pluimers

28

Ngoài những gì Andy đã đề cập, còn có một sự khác biệt khác có thể quan trọng - máy chủ ghi trực tiếp ghi vào máy chủ và không trả lại gì, có nghĩa là bạn không thể chuyển hướng đầu ra, ví dụ: vào một tệp.

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

Bây giờ chạy trong PowerShell:

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

Như đã thấy, bạn không thể chuyển hướng chúng vào một tập tin. Điều này có thể gây ngạc nhiên cho một người không cẩn thận.

Nhưng nếu chuyển sang sử dụng đầu ra ghi thay vào đó, bạn sẽ nhận được chuyển hướng hoạt động như mong đợi.


Bạn có thể nắm bắt Đầu ra máy chủ ghi nếu bạn sử dụng Powershell Bắt đầu xử lý. \ A.ps. -RedirectSt ChuẩnOutput somefile.txt Tuy nhiên, có vấn đề với mã hóa (tệp sẽ nằm trong SystemDefaultEncoding).
MKesper

16

Đây là một cách khác để thực hiện tương đương với Viết-Xuất. Chỉ cần đặt chuỗi của bạn trong dấu ngoặc kép:

"count=$count"

Bạn có thể đảm bảo rằng điều này hoạt động giống như Viết ra bằng cách chạy thử nghiệm này:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

Hai cái đầu tiên sẽ xuất "blah blah" ra out.txt, nhưng cái thứ ba sẽ không.

"help Write-Output" đưa ra gợi ý về hành vi này:

Lệnh ghép ngắn này thường được sử dụng trong các tập lệnh để hiển thị các chuỗi và các đối tượng khác trên bàn điều khiển. Tuy nhiên, vì hành vi mặc định là hiển thị các đối tượng ở cuối đường ống, nên thường không cần thiết phải sử dụng lệnh ghép ngắn.

Trong trường hợp này, chính chuỗi "Count = $ Count" là đối tượng ở cuối đường ống và được hiển thị.


6

Đối với việc sử dụng Write-Host, PSScriptAnalyzertạo ra các chẩn đoán sau:

Tránh sử dụng Write-Hostvì nó có thể không hoạt động trong tất cả các máy chủ, không hoạt động khi không có máy chủ và (trước PS 5.0) không thể bị chặn, bị bắt hoặc chuyển hướng. Thay vào đó, sử dụng Write-Output,Write-Verbose hoặc Write-Information.

Xem tài liệu đằng sau quy tắc đó để biết thêm thông tin. Đoạn trích cho hậu thế:

Việc sử dụng Write-Hostđược khuyến khích rất nhiều trừ khi sử dụng các lệnh vớiShow động từ. Các Showđộng từ có nghĩa một cách rõ ràng "hiển thị trên màn hình, không có khả năng khác".

Các lệnh với Show động từ không áp dụng kiểm tra này.

Jeffrey Snover có một bài đăng trên blog Write-Host được coi là có hại, trong đó ông tuyên bố Write-Host hầu như luôn là điều sai trái vì nó can thiệp vào tự động hóa và cung cấp thêm lời giải thích đằng sau chẩn đoán, tuy nhiên trên đây là một bản tóm tắt tốt.


3

Từ thử nghiệm của tôi, Write-Output và [Console] :: WriteLine () hoạt động tốt hơn nhiều so với Write-Host.

Tùy thuộc vào số lượng văn bản bạn cần viết ra, điều này có thể quan trọng.

Dưới đây nếu kết quả của 5 bài kiểm tra cho mỗi Máy chủ ghi, Đầu ra ghi và [Bảng điều khiển] :: WriteLine ().

Theo kinh nghiệm hạn chế của tôi, tôi đã tìm thấy khi làm việc với bất kỳ loại dữ liệu trong thế giới thực nào, tôi cần phải từ bỏ các lệnh ghép ngắn và đi thẳng tới các lệnh cấp thấp hơn để có được bất kỳ hiệu suất tốt nào trong các tập lệnh của tôi.

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-OutputWrite-Hostphục vụ các mục đích khác nhau, vì vậy không có điểm nào để so sánh hiệu suất của chúng. Có, sử dụng trực tiếp các loại .NET và phương thức của chúng nhanh hơn, nhưng bạn bỏ lỡ các tính năng cấp cao hơn mà các lệnh ghép ngắn PowerShell có thể cung cấp. [Console]::WriteLine()gần giống với Write-Hosttrường hợp hiện tại, nhưng sẽ không hoạt động trong mọi trường hợp, vì không phải tất cả các máy chủ PowerShell đều là bảng điều khiển .
mkuity0

0

Về [Bảng điều khiển] :: WriteLine () - bạn nên sử dụng nó nếu bạn sẽ sử dụng các đường ống dẫn trong CMD (không phải trong powershell). Giả sử bạn muốn ps1 truyền nhiều dữ liệu vào thiết bị xuất chuẩn và một số tiện ích khác để tiêu thụ / chuyển đổi nó. Nếu bạn sử dụng Write-Host trong tập lệnh thì nó sẽ chậm hơn nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.