Win*_*ing 454 c# command-line
如何从C#执行命令行程序并返回STD OUT结果.具体来说,我想对以编程方式选择的两个文件执行DIFF,并将结果写入文本框.是的,我可以为自己解决这个问题,但肯定有人做过类似的事情,我很懒...
小智 503
// 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();
Run Code Online (Sandbox Code Playgroud)
代码来自MSDN.
Jer*_*emy 141
这是一个快速示例:
//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();
Run Code Online (Sandbox Code Playgroud)
小智 100
还有一个我发现有用的参数,我用它来消除进程窗口
pProcess.StartInfo.CreateNoWindow = true;
Run Code Online (Sandbox Code Playgroud)
这有助于完全隐藏黑色控制台窗口,如果这是你想要的.
Lu5*_*u55 87
// 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) +
"'";
}
Run Code Online (Sandbox Code Playgroud)
Jef*_* Mc 13
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();
}
Run Code Online (Sandbox Code Playgroud)
Cam*_*ron 11
此页面上接受的答案有一个在极少数情况下很麻烦的弱点.有两个文件句柄,程序按惯例,stdout和stderr写入.如果您只是读取单个文件句柄(例如Ray的答案),并且您正在开始的程序将足够的输出写入stderr,它将填充输出stderr缓冲区并阻塞.然后你的两个进程陷入僵局.缓冲区大小可以是4K.这在短期程序中极为罕见,但如果你有一个长期运行的程序,它反复输出到stderr,它最终会发生.调试和跟踪这很棘手.
有几种很好的方法可以解决这个问题.
一种方法是执行cmd.exe而不是程序,并使用cmd.exe的/ c参数调用程序以及cmd.exe的"2>&1"参数,告诉它合并stdout和stderr.
var p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
Run Code Online (Sandbox Code Playgroud)另一种方法是使用一个同时读取两个句柄的编程模型.
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();
Run Code Online (Sandbox Code Playgroud)您将需要使用ProcessStartInfo与RedirectStandardOutput启用-那么你可以读取输出流.您可能会发现使用">"将输出重定向到文件(通过操作系统)更容易,然后只需读取文件即可.
[编辑:像雷一样:+1]
如果您不介意引入依赖项,CliWrap可以为您简化:
using CliWrap;
using CliWrap.Buffered;
var result = await Cli.Wrap("target.exe")
.WithArguments("arguments")
.ExecuteBufferedAsync();
var stdout = result.StandardOutput;
Run Code Online (Sandbox Code Playgroud)
由于这里的大多数答案都没有实现using声明IDisposable以及我认为可能有必要的其他一些内容,因此我将添加这个答案。
对于 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");
}
Run Code Online (Sandbox Code Playgroud)
这是一个小例子:
using System;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
var p = Process.Start(
new ProcessStartInfo("git", "branch --show-current")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
WorkingDirectory = Environment.CurrentDirectory
}
);
p.WaitForExit();
string branchName =p.StandardOutput.ReadToEnd().TrimEnd();
string errorInfoIfAny =p.StandardError.ReadToEnd().TrimEnd();
if (errorInfoIfAny.Length != 0)
{
Console.WriteLine($"error: {errorInfoIfAny}");
}
else {
Console.WriteLine($"branch: {branchName}");
}
}
}
Run Code Online (Sandbox Code Playgroud)
我相信这是最短的形式。
请注意,大多数命令行工具很容易混淆标准输出和标准错误,有时将它们组合成单个字符串是有意义的。
有时也p.ExitCode可能有用。
如果您想自己编写命令行实用程序(例如工具),上面的示例可用于编写命令行实用程序。请注意,对于 cli 自动化,还可以使用Cake Frosten和Cake Git 扩展。
一行运行命令:
new Process() { StartInfo = new ProcessStartInfo("echo", "Hello, World") }.Start();
Run Code Online (Sandbox Code Playgroud)
以最短的可读代码读取命令的输出:
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();
Run Code Online (Sandbox Code Playgroud)
如果您还需要在cmd.exe中执行某些命令,您可以执行以下操作:
// 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);
Run Code Online (Sandbox Code Playgroud)
这仅返回命令本身的输出:
您还可以使用StandardInput代替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);
Run Code Online (Sandbox Code Playgroud)
结果如下:
| 归档时间: |
|
| 查看次数: |
439668 次 |
| 最近记录: |