2011-07-03 3 views
3

기존 콘솔 응용 프로그램에 GUI를 제공하는 작은 포장 응용 프로그램이 있습니다. ProcessStartInfoProcess 클래스를 사용하여 .exe에 바인딩 한 다음 BeginErrorReadLine()BeginOutputReadLine()을 사용하여 메시지를 새 GUI로 리디렉션합니다. 콘솔이 Console.Write() 대신 Console.WriteLine()을 호출 할 때를 제외하고는 모두 잘 작동합니다.이 경우 Write에 전달 된 텍스트는 전혀 표시되지 않습니다. 나는 WriteLine 함수가 텍스트 뒤에 줄 바꿈을 삽입하고 Write 메서드가 그렇지 않기 때문에 문제가 있다고 생각합니다. 이 문제를 피할 방법이 있습니까? Write은 원래 명령 줄 프로그램에서 Write에서 WriteLine으로 변경할 수 없으므로 입력을 요청하는 데 Write이 사용됩니다.프로세스 래핑, 일부 출력이 표시되지 않습니다.

관련 코드 :

var startInfo = new ProcessStartInfo(ServerFile); 
startInfo.RedirectStandardInput = true; 
startInfo.RedirectStandardError = true; 
startInfo.RedirectStandardOutput = true; 

ServerProc = new Process(); 
ServerProc.StartInfo = startInfo; 
ServerProc.EnableRaisingEvents = true; 
ServerProc.ErrorDataReceived += new DataReceivedEventHandler(ServerProc_ErrorDataReceived); 
ServerProc.OutputDataReceived += new DataReceivedEventHandler(ServerProc_OutputDataReceived); 

private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
{ 
    Dispatcher.Invoke(new Action(() => 
    { 
     ConsoleTextBlock.Text += e.Data + "\r\n"; 
     ConsoleScroll.ScrollToEnd(); 
    })); 
} 

private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e) 
{ 
    Dispatcher.Invoke(new Action(() => 
    { 
     ConsoleTextBlock.Text += e.Data + "\r\n"; 
     ConsoleScroll.ScrollToEnd(); 
    })); 
} 

답변

2

발생한 문제는 Process 클래스가 프로세스의 출력의 편리한 라인 지향 이벤트 기반 처리를 위해 설정되어 있다는 점이다. 부분 행을 출력 할 때이 행을 읽어야 할 경우이 기능을 사용할 수 없습니다.

그럼에도 불구하고, Process 클래스는 라인 지향 기능보다 출력을 세밀하게 제어해야하는 경우 필요한 도구를 제공합니다. 출력을 리디렉션하는 경우 Process.StandardOutputStreamReader이고 전체 행을 읽지 않고 사용할 수있는 전체 StreamReader API가 있습니다.

예를 들어

, 여기에 표준 출력의 읽기 문자 대 문자 :

Console.Write("abc"); 
Thread.Sleep(1000); 
Console.WriteLine("def"); 

그것은 생산 :

var start = DateTime.Now; 
int n; 
while ((n = ServerProc.StandardOutput.Read()) != -1) 
{ 
    var c = (char)n; 
    var delta = (DateTime.Now - start).TotalMilliseconds; 
    Console.WriteLine("c = {0} (0x{1:X}) delta = {2}", 
     char.IsWhiteSpace(c) ? '*' : c, n, delta); 
} 

우리는이 출력을 생성 다른 콘솔 프로그램을 실행하는 경우 이 출력은

c = a (0x61) delta = 44.0025 
c = b (0x62) delta = 44.0025 
c = c (0x63) delta = 44.0025 
c = d (0x64) delta = 1109.0634 
c = e (0x65) delta = 1110.0635 
c = f (0x66) delta = 1110.0635 
c = * (0xD) delta = 1110.0635 
c = * (0xA) delta = 1110.0635 

이며 "abc"은 1 초 나머지 줄 앞에.

그러나 이벤트 지향 I/O가 이미 Process에서 제공되는 것이 좋으면이 방법은 편리하지 않습니다. 다음 중 하나를 수행 할 수 있습니다 :

  • 사용 비동기 Stream API 차단이

을 읽고 심지어 사용자의 요구를 충족 자신의 이벤트 기반의 I/O를 출시 할

  • 사용 스레드.

    다른 프로그램의 문자 지향 출력을 구문 분석하는 프로그램을 작성 중이므로 전체 줄을 사용하지 않고 "지금 당분간 프로그램 출력이 완료되었음을 나타냅니다."라는 표시로 어떤 종류의 시간 제한이 필요합니다. 이것은 출력이 얼마나 예측 가능한지에 따라 쉽거나 어렵습니다. 예를 들어 "?"으로 끝나는 프롬프트를 인식 할 수 있습니다. 그것은 당신의 상황에 달려 있습니다.

    중요한 점은 라인 지향 I/O 이외의 다른 것을 원할 경우 StandardOutputStandardErrorStreamReader 속성을 사용해야한다는 것입니다.

  • +0

    Sladkey 내가 비동기 및 동기 읽기를 사용할 때의 문제점은 필자가 직접 이벤트 기반이 아닌 쓰기 기능을 수동으로 호출해야한다는 것입니다. 이 올바른지? 가장 좋은 해결책은 타이머와 같을까요? – shmeeps

    +0

    프로그램의 출력을 파싱하려면 파서를 작성해야합니다. 파서를 스레드로 작성하는 것이 가장 쉽습니다. 그렇지 않으면 상태 시스템이 필요합니다. 출력이 결정 론적이라면 타이머를 전혀 필요로하지 않습니다. 이 작업은 간단한 작업이 아니며 솔루션은 사용자의 필요와 응용 프로그램에 따라 다릅니다. 이 디자인은 구문 분석 스레드와의 협력이 필요하며 이벤트를 사용하는 것이 가장 쉽습니다. 그 외에도 많은 실용적인 접근 방식이 있습니다! –

    관련 문제