问答中心分类: C#如何:在C#中执行命令行,获取STD OUT结果
0
匿名用户 提问 1月 前

如何从C#执行命令行程序并返回STD OUT结果?具体来说,我想对通过编程选择的两个文件执行DIFF,并将结果写入文本框。

17 Answers
0
Jeremy 回答 1月 前

下面是一个快速示例:

//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();
Suman 回复 1月 前

+1用于显示如何在运行命令行程序时添加参数(可接受的答案没有)

0
Peter Du 回答 1月 前

还有一个我发现很有用的参数,我用它来消除进程窗口

pProcess.StartInfo.CreateNoWindow = true;

这有助于对用户完全隐藏黑色控制台窗口,如果您希望这样做的话。

The Vivandiere 回复 1月 前

帮我省去了很多头痛。谢谢

Pedro 回复 1月 前

调用“sc”时,我还必须设置StartInfo。WindowStyle=处理WindowStyle。隐藏的

0
Ilya Serbis 回答 1月 前
// 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) +
        "'";
}
ShahidAzim 回复 1月 前

非常全面的示例,谢谢

Paul Williams 回复 1月 前

可能需要将OutputDataReceived处理程序更改为标准输出。附录行()

ProfK 回复 1月 前

在我看来,这是一个比公认的答案更全面的解决方案。我现在正在使用它,还没有使用公认的,但那一个看起来真的很缺乏。

JohnB 回复 1月 前

感谢process.StartInfo.RedirectStandardError = true;if (process.ExitCode == 0)哪个公认的答案没有。

Soren 回复 1月 前

谢谢,它可以在Ubuntu 20 LTS上运行。(仅供记录)

0
Cameron 回答 1月 前

本页上公认的答案有一个缺点,在极少数情况下很麻烦。程序按约定写入的文件句柄有两个:stdout和stderr。
有几种很好的方法可以解决这个问题。

  1. 一种方法是执行cmd。exe而不是您的程序,并使用cmd的/c参数。exe调用您的程序以及cmd的“2>&1”参数。exe命令它合并stdout和stderr。
    var p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c mycmd.exe 2>&1";
  2. 另一种方法是使用同时读取两个句柄的编程模型。
    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();
TinyRacoon 回复 1月 前

我认为这更好地回答了最初的问题,因为它显示了如何通过C#(不是文件)运行CMD命令。

0
Jeff Mc 回答 1月 前
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();
 }
JensG 回复 1月 前

进程写入大量数据时可能会死锁。最好在进程仍在运行时开始读取数据。