[C#] 방법 : C #에서 명령 줄 실행, STD OUT 결과 가져 오기

C #에서 명령 줄 프로그램을 실행하고 STD OUT 결과를 다시 얻으려면 어떻게해야합니까? 특히 프로그래밍 방식으로 선택된 두 파일에서 DIFF를 실행하고 결과를 텍스트 상자에 쓰고 싶습니다.



답변

// 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();

코드는 MSDN 에서 가져온 것 입니다.


답변

다음은 간단한 샘플입니다.

//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();


답변

프로세스 창을 제거하는 데 유용한 다른 매개 변수가 있습니다.

pProcess.StartInfo.CreateNoWindow = true;

원하는 경우 사용자에게 검은 색 콘솔 창을 완전히 숨기는 데 도움이됩니다.


답변

// 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) +
        "'";
}


답변

이 페이지에서 허용되는 답변은 드문 상황에서 문제가되는 약점을 가지고 있습니다. 프로그램이 표준, stdout 및 stderr로 쓰는 두 개의 파일 핸들이 있습니다. Ray의 응답과 같은 단일 파일 핸들을 읽고 시작하는 프로그램이 stderr에 충분한 출력을 쓰면 출력 stderr 버퍼 및 블록을 채 웁니다. 그런 다음 두 프로세스가 교착 상태가됩니다. 버퍼 크기는 4K 일 수 있습니다. 이것은 단기 프로그램에서는 극히 드물지만 stderr에 반복적으로 출력되는 장기 실행 프로그램이 있으면 결국 발생합니다. 디버깅 및 추적이 까다 롭습니다.

이것을 처리하는 몇 가지 좋은 방법이 있습니다.

  1. 한 가지 방법은 프로그램 대신 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";
    
  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();
    

답변

 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();
 }


답변

당신은 사용해야합니다 ProcessStartInfo함께 RedirectStandardOutput다음 출력 스트림을 읽을 수 – 수있었습니다. “>”를 사용하여 출력을 파일로 리디렉션하고 (OS를 통해)보다 쉽게 ​​파일을 읽을 수 있습니다.

[편집 : 레이가 한 것처럼 : +1]