.NET 애플리케이션 (C #)에서 콘솔 출력 캡처


130

.NET 애플리케이션에서 콘솔 애플리케이션을 호출하고 콘솔에서 생성 된 모든 출력을 캡처하려면 어떻게해야합니까?

(정보를 먼저 파일에 저장 한 다음 실시간으로 받기를 원하므로 다시 나열하고 싶지는 않습니다.)



두 질문 모두의 날짜를보고 어느 것이 "중복"인지 확인하십시오
Gripsoft

"가능한 복제물"은 정리할 수있는 방법입니다. 비슷한 질문을 닫고 최상의 답변을 유지하십시오. 날짜는 필수가 아닙니다. 질문이 훨씬 새롭고 최신 답변이있는 경우에도 중복 질문을 마감하려면 투표해야합니까?를 참조하십시오 . 설명이 필요하다는 데 동의 하면 "중복 가능"자동 설명에 설명 추가 링크
Michael Freidgeim

답변:


163

ProcessStartInfo.RedirectStandardOutput 속성을 사용하면 쉽게 얻을 수 있습니다 . 전체 샘플은 링크 된 MSDN 설명서에 포함되어 있습니다. 유일한 경고는 응용 프로그램의 모든 출력을 보려면 표준 오류 스트림을 리디렉션해야 할 수도 있다는 것입니다.

Process compiler = new Process();
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();    

Console.WriteLine(compiler.StandardOutput.ReadToEnd());

compiler.WaitForExit();

3
끝에 새 줄을 추가하지 않으려면 Console.Write대신 사용하십시오.
tm1

2
ReadToEnd ()를 콘솔 응용 프로그램과 함께 사용하면 사용자에게 입력을 요구하는 기능이 있습니다. 예 : 파일 덮어 쓰기 : Y 또는 N? 그런 다음 ReadToEnd는 사용자 입력을 기다리는 동안 프로세스가 종료되지 않으므로 메모리 누수가 발생할 수 있습니다. 출력을 캡처하는보다 안전한 방법은 process.OutputDataReceived 이벤트 핸들러를 사용하고 프로세스가 애플리케이션에 출력을 수신하도록 알리는 것입니다.
Baaleos

compiler.StartInfo.FileName = "csc.exe"이후 코드가 azure webapp에 배포 된 경우 캡처하는 방법; 존재하지 않을 수도 있습니다!
Asif Iqbal

compiler.StartInfo.FileName = "csc.exe"이후 코드가 azure webapp에 배포 된 경우 캡처하는 방법; 존재하지 않을 수도 있습니다!
Asif Iqbal

37

이것은 @mdb 에서 허용되는 답변보다 약간 개선 되었습니다 . 특히 프로세스의 오류 출력도 캡처합니다. 또한 오류와 일반 출력을 모두ReadToEnd() 캡처하려는 경우 작동하지 않기 때문에 이벤트를 통해 이러한 출력 을 캡처 합니다 . 실제로 BeginxxxReadLine()전화 가 필요하기 때문에이 작업을하는 데 시간이 걸렸습니다 Start().

비동기 방식 :

using System.Diagnostics;

Process process = new Process();

void LaunchProcess()
{
    process.EnableRaisingEvents = true;
    process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
    process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
    process.Exited += new System.EventHandler(process_Exited);

    process.StartInfo.FileName = "some.exe";
    process.StartInfo.Arguments = "param1 param2";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;

    process.Start();
    process.BeginErrorReadLine();
    process.BeginOutputReadLine();          

    //below line is optional if we want a blocking call
    //process.WaitForExit();
}

void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
}

void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine(e.Data + "\n");
}

void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine(e.Data + "\n");
}

5
고마워요, 오랫동안 이것을 찾고있었습니다!
C Bauer

3
감사합니다. 이것은 완벽 해요.
DrFloyd5

1
당신은 내 응용 프로그램의 감사 목록에 명예의 장소를 얻을 것입니다.
marsh-wiggle


7

ConsoleAppLauncher 는 해당 질문에 대답하기 위해 특별히 제작 된 오픈 소스 라이브러리입니다. 콘솔에서 생성 된 모든 출력을 캡처하고 콘솔 응용 프로그램을 시작하고 닫는 간단한 인터페이스를 제공합니다.

ConsoleOutput 이벤트는 콘솔이 표준 / 오류 출력에 새 줄을 쓸 때마다 발생합니다. 줄이 대기되고 출력 순서를 따르도록 보장됩니다.

NuGet 패키지 로도 제공 .

전체 콘솔 출력을 얻기위한 샘플 호출 :

// Run simplest shell command and return its output.
public static string GetWindowsVersion()
{
    return ConsoleApp.Run("cmd", "/c ver").Output.Trim();
}

실시간 피드백이있는 샘플 :

// Run ping.exe asynchronously and return roundtrip times back to the caller in a callback
public static void PingUrl(string url, Action<string> replyHandler)
{
    var regex = new Regex("(time=|Average = )(?<time>.*?ms)", RegexOptions.Compiled);
    var app = new ConsoleApp("ping", url);
    app.ConsoleOutput += (o, args) =>
    {
        var match = regex.Match(args.Line);
        if (match.Success)
        {
            var roundtripTime = match.Groups["time"].Value;
            replyHandler(roundtripTime);
        }
    };
    app.Run();
}

2

콘솔 출력 및 입력을 통해 다른 프로세스와의 상호 작용을 쉽게 스크립트 할 수 있는 O2 플랫폼 (오픈 소스 프로젝트)에 여러 가지 도우미 메소드를 추가했습니다 ( http://code.google.com/p/o2platform/ 참조) . 소스 / 찾아보기 / 트렁크 /O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs )

또한 기존 프로세스 또는 팝업 창에서 현재 프로세스의 콘솔 출력을 볼 수있는 API가 유용 할 수 있습니다. 자세한 내용은이 블로그 게시물을 참조하십시오. http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (이 블로그에는 소비 방법에 대한 세부 정보도 포함되어 있습니다. 새로운 프로세스의 콘솔 출력)


그 이후로 ConsoleOut 사용에 대한 추가 지원을 추가했습니다 (이 경우 .NET 프로세스를 직접 시작하면). 살펴보기 : C # REPL에서 콘솔 출력을 사용하는 방법 , Visual Studio IDE에 'Console Out'을 기본 창으로 추가 , UserControls
Dinis Cruz에서

2

stdOut 및 StdErr에 대한 콜백을 허용하는 반응 버전을 만들었습니다.
onStdOutonStdErr, 비동기 적으로 호출되는
즉시 데이터 (프로세스 종료하기 전에)에 도착한다.

public static Int32 RunProcess(String path,
                               String args,
                       Action<String> onStdOut = null,
                       Action<String> onStdErr = null)
    {
        var readStdOut = onStdOut != null;
        var readStdErr = onStdErr != null;

        var process = new Process
        {
            StartInfo =
            {
                FileName = path,
                Arguments = args,
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardOutput = readStdOut,
                RedirectStandardError = readStdErr,
            }
        };

        process.Start();

        if (readStdOut) Task.Run(() => ReadStream(process.StandardOutput, onStdOut));
        if (readStdErr) Task.Run(() => ReadStream(process.StandardError, onStdErr));

        process.WaitForExit();

        return process.ExitCode;
    }

    private static void ReadStream(TextReader textReader, Action<String> callback)
    {
        while (true)
        {
            var line = textReader.ReadLine();
            if (line == null)
                break;

            callback(line);
        }
    }


사용법 예

다음과 executable함께 실행 args되고 인쇄됩니다.

  • 흰색 stdOut
  • 빨간색 stdErr

콘솔에.

RunProcess(
    executable,
    args,
    s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
    s => { Console.ForegroundColor = ConsoleColor.Red;   Console.WriteLine(s); } 
);

1

에서 파이썬 Programcıları Derneği, 전자 kitap, örnek - PythonTR :

Process p = new Process();   // Create new object
p.StartInfo.UseShellExecute = false;  // Do not use shell
p.StartInfo.RedirectStandardOutput = true;   // Redirect output
p.StartInfo.FileName = "c:\\python26\\python.exe";   // Path of our Python compiler
p.StartInfo.Arguments = "c:\\python26\\Hello_C_Python.py";   // Path of the .py to be executed

1

process.StartInfo.**CreateNoWindow** = true;및을 추가했습니다 timeout.

private static void CaptureConsoleAppOutput(string exeName, string arguments, int timeoutMilliseconds, out int exitCode, out string output)
{
    using (Process process = new Process())
    {
        process.StartInfo.FileName = exeName;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.CreateNoWindow = true;
        process.Start();

        output = process.StandardOutput.ReadToEnd();

        bool exited = process.WaitForExit(timeoutMilliseconds);
        if (exited)
        {
            exitCode = process.ExitCode;
        }
        else
        {
            exitCode = -1;
        }
    }
}

사용 StandardOutput.ReadToEnd()하면 앱이 끝날 때까지 다음 문장으로 돌아 가지 않습니다. 따라서 WaitForExit (timeoutMilliseconds)의 시간 초과가 작동하지 않습니다! (코드가 중단됩니다!)
S.Serpooshan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.