2010-02-27 35 views
6

Tôi biết rằng có stdout/in/err cho một chương trình và tôi muốn chuyển hướng đầu ra của chương trình sang một tệp thay vì đầu ra của bàn điều khiển. Và bây giờ tôi hình dung nó ra với mã dưới đây:Làm cách nào để ghi trực tiếp vào luồng StdOut của chương trình trong C#?

FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate); 
StreamWriter sw = new StreamWriter(fs); 
TextWriter old = Console.Out; 
Console.SetOut(sw); 
Console.Write("bbb"); 
sw.Flush(); 

Nhưng phương pháp này là để kết nối các chương trình stdout-Console.Out và chuyển hướng Console.Out đến tập tin. Đó là loại như thế này:

Program.StdOut -> Console.Out -> File

Các Console.Out đây có vẻ là một cây cầu. Tôi không muốn cây cầu này và tôi không muốn sử dụng Bảng điều khiển .Write() để tạo đầu ra. Làm cách nào tôi có thể ánh xạ luồng xuất bản của chương trình tới tệp đích trực tiếp và ghi trực tiếp vào chương trình thay vì Console.Write()? Những gì tôi muốn là loại như thế này:

Program.StdOut -> Tệp

Các Process.StandardOutput tài sản duy nhất mang lại cho tôi một readonly StreamReader đối tượng. Làm thế nào để viết cho Process.StandardOutput ?? Hoặc ở đâu là thiết bị xuất chuẩn của tại số?

Rất cám ơn.

Trả lời

6

Bạn có thể nhận lệnh giữ ứng dụng bằng cách gọi Console.OpenStandardOutput. Từ đó, bạn có thể làm bất cứ điều gì bạn muốn với luồng, mặc dù bạn sẽ không thể gán lại nó. Nếu bạn muốn làm điều đó, bạn sẽ phải P/Gọi SetStdHandle và tự xử lý các chi tiết.

EDIT: nhập mã ví dụ cho P/Gọi tuyến đường:

[DllImport("kernel32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetStdHandle(int nStdHandle, IntPtr nHandle); 

const int STD_OUTPUT_HANDLE = -11; 

static void RedirectStandardOutput(FileStream file) 
{ 
    SetStdHandle(STD_OUTPUT_HANDLE, file.SafeFileHandle.DangerousGetHandle()); 
} 
+0

Cảm ơn, MikeP. Tôi tự hỏi tại sao cho lớp Console yêu cầu phương thức OpenStandardOutput(), tại sao không phân loại phương thức này trong lớp Process, tôi nghĩ điều đó sẽ hợp lý hơn. Loại triết lý thiết kế nào có liên quan? – smwikipedia

+0

Tôi không biết tại sao họ lại chọn phương pháp này. – MikeP

1

sử dụng ProcessStartInfo và xử lý lớp học và đặt RedirectStandardOutput thành true, sau đó bạn có thể nắm bắt đầu ra từ luồng.

ProcessStartInfo info = new ProcessStartInfo("process.exe", "-arg1 -arg2"); 
info.RedirectStandardOutput = true; 
Process p = Process.Start(info); 
p.Start(); 
string output = p.StandardOutput.ReadToEnd(); 
+1

Cảm ơn, Jake. Tôi muốn biết rằng trong process.exe, làm thế nào để ghi vào đầu ra tiêu chuẩn của chương trình? Loại mã nào thực hiện điều đó? Nó vẫn là một Console.Write()? Có cách nào không sử dụng phương pháp này và ghi trực tiếp vào chương trình xuất chuẩn của chương trình không? – smwikipedia

+0

Bạn cần phát đầu ra của chương trình cho cả StdOut và luồng thứ 2 của bạn.Một cách là viết một vòng lặp gọi là 'ReadToEnd()', ghi vào cả hai đầu ra, sau đó ngủ một chút, lặp lại cho đến khi luồng đã được đóng lại. – spoulson

+0

Đặt 'info.UseShellExecute = false' và' p.StanardInput.Write() 'để gửi dữ liệu đến quy trình. Nếu quá trình này lặp lại dữ liệu, bạn tốt, nhưng bạn không thể chỉ chiếm đoạt quy trình và sử dụng xử lý StandardOutput của nó như là của riêng bạn. – Jake

6

Bạn có thể không nên đặt các thiết bị xuất chuẩn của quá trình của riêng bạn. Lý do nó là stdout là để người gọi (dòng lệnh, bất cứ điều gì) có thể chuyển hướng nó bất cứ nơi nào nó cần, mà không cần chương trình của bạn phải biết.

Đó là cách những thứ như "nhập foo.txt | thêm" hoạt động. Nếu lệnh type cảm thấy tự do để xác định lại stdout thành một tệp, điều đó sẽ không hoạt động chút nào.

Nếu bạn muốn ghi vào luồng, chỉ cần mở luồng và ghi vào luồng đó.

Các vấn đề liên quan