Làm cách nào để tôi thực hiện chương trình dòng lệnh từ C # và lấy lại kết quả STD OUT? Cụ thể, tôi muốn thực thi DIFF trên hai tệp được chọn theo chương trình và ghi kết quả vào hộp văn bản.
Làm cách nào để tôi thực hiện chương trình dòng lệnh từ C # và lấy lại kết quả STD OUT? Cụ thể, tôi muốn thực thi DIFF trên hai tệp được chọn theo chương trình và ghi kết quả vào hộp văn bản.
Câu trả lời:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "YOURBATCHFILE.bat";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Mã là từ MSDN .
{YourProcessObject}.StartInfo.Arguments
chuỗi.
p.StandardError
luồng. Khi luồng đầy, có vẻ như quá trình sẽ tạm dừng cho đến khi dữ liệu được tiêu thụ, vì vậy tôi phải đọc cả hai StandardError
và StandardOutput
để đảm bảo rằng một tác vụ thực thi chính xác.
Đây là một mẫu nhanh:
//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = strCommand;
//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = strCommandParameters;
pProcess.StartInfo.UseShellExecute = false;
//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;
//Optional
pProcess.StartInfo.WorkingDirectory = strWorkingDirectory;
//Start the process
pProcess.Start();
//Get program output
string strOutput = pProcess.StandardOutput.ReadToEnd();
//Wait for process to finish
pProcess.WaitForExit();
Có một tham số khác tôi thấy hữu ích, mà tôi sử dụng để loại bỏ cửa sổ quy trình
pProcess.StartInfo.CreateNoWindow = true;
Điều này giúp ẩn hoàn toàn cửa sổ giao diện điều khiển màu đen khỏi người dùng, nếu đó là những gì bạn mong muốn.
// usage
const string ToolFileName = "example.exe";
string output = RunExternalExe(ToolFileName);
public string RunExternalExe(string filename, string arguments = null)
{
var process = new Process();
process.StartInfo.FileName = filename;
if (!string.IsNullOrEmpty(arguments))
{
process.StartInfo.Arguments = arguments;
}
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
var stdOutput = new StringBuilder();
process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); // Use AppendLine rather than Append since args.Data is one line of output, not including the newline character.
string stdError = null;
try
{
process.Start();
process.BeginOutputReadLine();
stdError = process.StandardError.ReadToEnd();
process.WaitForExit();
}
catch (Exception e)
{
throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e);
}
if (process.ExitCode == 0)
{
return stdOutput.ToString();
}
else
{
var message = new StringBuilder();
if (!string.IsNullOrEmpty(stdError))
{
message.AppendLine(stdError);
}
if (stdOutput.Length != 0)
{
message.AppendLine("Std output:");
message.AppendLine(stdOutput.ToString());
}
throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message);
}
}
private string Format(string filename, string arguments)
{
return "'" + filename +
((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) +
"'";
}
process.StartInfo.RedirectStandardError = true;
và if (process.ExitCode == 0)
câu trả lời được chấp nhận không có.
Câu trả lời được chấp nhận trên trang này có một điểm yếu là rắc rối trong các tình huống hiếm gặp. Có hai tệp xử lý mà các chương trình ghi theo quy ước, thiết bị xuất chuẩn và thiết bị xuất chuẩn. Nếu bạn chỉ đọc một tệp xử lý đơn lẻ như câu trả lời từ Ray và chương trình bạn đang bắt đầu ghi đủ đầu ra cho thiết bị lỗi chuẩn, nó sẽ lấp đầy bộ đệm và khối stderr đầu ra. Sau đó, hai quá trình của bạn đang bế tắc. Kích thước bộ đệm có thể là 4K. Điều này là cực kỳ hiếm trên các chương trình có thời gian ngắn, nhưng nếu bạn có một chương trình chạy dài liên tục xuất ra stderr, điều đó sẽ xảy ra cuối cùng. Đây là khó khăn để gỡ lỗi và theo dõi.
Có một vài cách tốt để đối phó với điều này.
Một cách là thực thi cmd.exe thay vì chương trình của bạn và sử dụng đối số / c để cmd.exe để gọi chương trình của bạn cùng với đối số "2> & 1" tới cmd.exe để yêu cầu nó hợp nhất stdout và stderr.
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
Một cách khác là sử dụng một mô hình lập trình đọc cả hai tay cầm cùng một lúc.
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = @"/c dir \windows";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = false;
p.OutputDataReceived += (a, b) => Console.WriteLine(b.Data);
p.ErrorDataReceived += (a, b) => Console.WriteLine(b.Data);
p.Start();
p.BeginErrorReadLine();
p.BeginOutputReadLine();
p.WaitForExit();
System.Diagnostics.ProcessStartInfo psi =
new System.Diagnostics.ProcessStartInfo(@"program_to_call.exe");
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
System.Diagnostics.Process proc = System.Diagnostics.Process.Start(psi); ////
System.IO.StreamReader myOutput = proc.StandardOutput;
proc.WaitForExit(2000);
if (proc.HasExited)
{
string output = myOutput.ReadToEnd();
}
Bạn sẽ cần sử dụng ProcessStartInfo
với RedirectStandardOutput
kích hoạt - sau đó bạn có thể đọc luồng đầu ra. Bạn có thể thấy dễ dàng hơn khi sử dụng ">" để chuyển hướng đầu ra sang tệp (thông qua HĐH), sau đó chỉ cần đọc tệp.
[chỉnh sửa: như những gì Ray đã làm: +1]
RedirectStandardOutput
thực sự.
Điều này có thể hữu ích cho ai đó nếu bạn cố truy vấn bộ đệm ARP cục bộ trên PC / Server.
List<string[]> results = new List<string[]>();
using (Process p = new Process())
{
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = "/c arp -a";
p.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
p.Start();
string line;
while ((line = p.StandardOutput.ReadLine()) != null)
{
if (line != "" && !line.Contains("Interface") && !line.Contains("Physical Address"))
{
var lineArr = line.Trim().Split(' ').Select(n => n).Where(n => !string.IsNullOrEmpty(n)).ToArray();
var arrResult = new string[]
{
lineArr[0],
lineArr[1],
lineArr[2]
};
results.Add(arrResult);
}
}
p.WaitForExit();
}
Lệnh chạy một lớp lót:
new Process() { StartInfo = new ProcessStartInfo("echo", "Hello, World") }.Start();
Đọc đầu ra của lệnh với số lượng mã khả thi ngắn nhất:
var cliProcess = new Process() {
StartInfo = new ProcessStartInfo("echo", "Hello, World") {
UseShellExecute = false,
RedirectStandardOutput = true
}
};
cliProcess.Start();
string cliOut = cliProcess.StandardOutput.ReadToEnd();
cliProcess.WaitForExit();
cliProcess.Close();
Có một lớp ProcessHelper trong mã nguồn mở PublicDomain có thể khiến bạn quan tâm.
Trong trường hợp bạn cũng cần thực thi một số lệnh trong cmd.exe, bạn có thể làm như sau:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C vol";
p.Start();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Điều này chỉ trả về đầu ra của chính lệnh:
Bạn cũng có thể sử dụng StandardInput
thay vì StartInfo.Arguments
:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.Start();
// Read the output stream first and then wait.
p.StandardInput.WriteLine("vol");
p.StandardInput.WriteLine("exit");
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Kết quả trông như thế này:
Để giải trí, đây là giải pháp hoàn chỉnh của tôi để nhận đầu ra PYTHON - dưới một nút bấm - với báo cáo lỗi. Chỉ cần thêm một nút gọi là "butPython" và nhãn gọi là "llHello" ...
private void butPython(object sender, EventArgs e)
{
llHello.Text = "Calling Python...";
this.Refresh();
Tuple<String,String> python = GoPython(@"C:\Users\BLAH\Desktop\Code\Python\BLAH.py");
llHello.Text = python.Item1; // Show result.
if (python.Item2.Length > 0) MessageBox.Show("Sorry, there was an error:" + Environment.NewLine + python.Item2);
}
public Tuple<String,String> GoPython(string pythonFile, string moreArgs = "")
{
ProcessStartInfo PSI = new ProcessStartInfo();
PSI.FileName = "py.exe";
PSI.Arguments = string.Format("\"{0}\" {1}", pythonFile, moreArgs);
PSI.CreateNoWindow = true;
PSI.UseShellExecute = false;
PSI.RedirectStandardError = true;
PSI.RedirectStandardOutput = true;
using (Process process = Process.Start(PSI))
using (StreamReader reader = process.StandardOutput)
{
string stderr = process.StandardError.ReadToEnd(); // Error(s)!!
string result = reader.ReadToEnd(); // What we want.
return new Tuple<String,String> (result,stderr);
}
}
Vì hầu hết các câu trả lời ở đây không thực hiện sự trì using
trệ IDisposable
và một số nội dung khác tôi nghĩ có thể không cần thiết nên tôi sẽ thêm câu trả lời này.
Dành cho C # 8.0
// Start a process with the filename or path with filename e.g. "cmd". Please note the
//using statemant
using myProcess.StartInfo.FileName = "cmd";
// add the arguments - Note add "/c" if you want to carry out tge argument in cmd and
// terminate
myProcess.StartInfo.Arguments = "/c dir";
// Allows to raise events
myProcess.EnableRaisingEvents = true;
//hosted by the application itself to not open a black cmd window
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.CreateNoWindow = true;
// Eventhander for data
myProcess.Exited += OnOutputDataRecived;
// Eventhandler for error
myProcess.ErrorDataReceived += OnErrorDataReceived;
// Eventhandler wich fires when exited
myProcess.Exited += OnExited;
// Starts the process
myProcess.Start();
//read the output before you wait for exit
myProcess.BeginOutputReadLine();
// wait for the finish - this will block (leave this out if you dont want to wait for
// it, so it runs without blocking)
process.WaitForExit();
// Handle the dataevent
private void OnOutputDataRecived(object sender, DataReceivedEventArgs e)
{
//do something with your data
Trace.WriteLine(e.Data);
}
//Handle the error
private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Trace.WriteLine(e.Data);
//do something with your exception
throw new Exception();
}
// Handle Exited event and display process information.
private void OnExited(object sender, System.EventArgs e)
{
Trace.WriteLine("Process exited");
}