.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에 대한 콜백을 허용하는 반응 버전을 만들었습니다.
onStdOut와 onStdErr, 비동기 적으로 호출되는
즉시 데이터 (프로세스 종료하기 전에)에 도착한다.

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.