2016-10-12 5 views
1

내 WinForm 응용 프로그램에서 콘솔 응용 프로그램의 출력을 실시간으로 (cmd.exe를 통해 실행하는 것과 동일하게) 얻고 싶습니다. UI 작업이 아닌 스레드에서 수행하는 모든 작업 (BackgroundWorker의 메서드 bwRezerve_DoWork 사용). AddTextToTextbox Invoke를 사용하여 UI를 업데이트하십시오.실시간으로 다른 응용 프로그램 표준 출력을 받으십시오.

하지만 지금은 응용 프로그램이 종료 될 때만 출력을받습니다. 많은 질문을 여기에서 읽고 다른 사이트에서 비슷한 질문을 Capture output of process synchronously (i.e. "when it happens") 읽고 있지만 여전히 해결책을 찾을 수 없습니다. 여기 코드 : 또한

private void bwRezerve_DoWork(object sender, DoWorkEventArgs e) 
{ 
    proc = new Process 
    { 
     StartInfo = new ProcessStartInfo 
     { 
      FileName = Application.StartupPath + Path.DirectorySeparatorChar + "7z.exe", 
      Arguments = e.Argument, 
      UseShellExecute = false, 
      RedirectStandardOutput = true, 
      RedirectStandardError = true, 
      CreateNoWindow = true, 
     } 
    }; 
    proc.EnableRaisingEvents = true; 
    proc.OutputDataReceived += (who, what) => AddTextToTextbox(what.Data); 
    proc.ErrorDataReceived += (who, what) => AddTextToTextbox(what.Data); 

    proc.Start(); 
    proc.BeginOutputReadLine(); 
    proc.BeginErrorReadLine(); 
    //same result with next line commented 
    proc.WaitForExit(5 * 60 * 1000); 
} 

내가 대신 OutputDataReceived의이 시도했지만 결과는이 코드

private void bwRezerve_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ProcessStartInfo psi = new ProcessStartInfo(); 
    psi.FileName = Application.StartupPath + Path.DirectorySeparatorChar + "7z.exe"; 
    psi.Arguments = e.Argument; 
    psi.UseShellExecute = false; 
    psi.RedirectStandardError = true; 
    psi.RedirectStandardOutput = true; 
    psi.CreateNoWindow = true; 

    Process proc = Process.Start(psi); 
    proc.WaitForExit(); 

    while (!proc.StandardOutput.EndOfStream) 
    { 
     string line = proc.StandardOutput.ReadLine(); 
     AddTextToTextbox(line); 
    } 
} 

답변

1

입니다 프로세스가 완료 될 때만 출력이 표시되도록 스레드가 주 스레드에서 실행 중입니다. 배경 작업자 또는 스레드를 사용해야하므로 디스패처를 사용하여 현재 프로세스의 출력을 얻을 수도 있습니다.

while (!proc.StandardOutput.EndOfStream) 
{ 

    Application.Current.Dispatcher.Invoke(new Action(() => 
    { 
    string line = proc.StandardOutput.ReadLine(); 
    AddTextToTextbox(line); 
    }), null); 

} 

는 윈도우 기반 해방을 사용하여 현재 디스패처를 얻을 수 있습니다 당신을 위해 그 일 ..

편집

를 바랍니다.

어셈블리 : (수 WindowsBase.dll에서) WindowsBase (Ref MSDN)

System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(new Action(() => 
      { 
       string line = proc.StandardOutput.ReadLine(); 
       AddTextToTextbox(line); 
      }), null); 
+0

이 경우 입력을 전혀받지 못했습니다. – Varro

+0

업데이트 된 코드 시도 – Mostafiz

+0

ReadLine()과 ReadToEnd()를 모두 사용했습니다. 결과는 동일합니다. – Varro

1

내가 문제와 문제가 있다고 생각을 해보십시오 같은

while (!proc.StandardOutput.EndOfStream) 
{ 
    string line = proc.StandardOutput.ReadLine(); 
    AddTextToTextbox(line); 
} 
+0

WPF가 아닌 WinForms 프로젝트이므로 "Application.Current.Dispatcher.Invoke"를 사용할 수 없습니다. 하지만 BackgroundWorker (bwRezerve_DoWork)에서 수행하는 모든 작업. 그리고 "AddTextToTextbox"메서드에서 Invoke를 사용하여 UI 스레드에서 업데이트를 수행합니다. – Varro

+0

진행할 필요가 없습니다. 결과가 필요합니다 (해당). 콘솔 애플리케이션 자체는 퍼센티지를 전송하지 않습니다. – Varro

+0

같은 결과 - 콘솔 응용 프로그램이 종료 된 후에 출력이 표시됩니다 (예, 'WaitForExit()'는 코드 블록 이후 임). – Varro

0

7zip과 표준 출력을 사용하지 않습니다 - 그것은 지속적으로 화면을 다시 작성하기 때문에 쉽게 (진행 상황을 표시하는) 것을 볼 수 있습니다 . 스트리밍 할 방법이 없습니다.

+0

하지만 어떻게 든 7zip은 cmd.exe로 데이터를 보냅니다. 그렇습니까? 그리고 나는이 자료를보고 싶다. – Varro

+0

@Varro 아니요. 'cmd'는 아무 관련이 없습니다. 단지 명령 프로세서 일뿐입니다. 데이터를 콘솔에 직접 보내고, 응용 프로그램에 콘솔을 만들면'cmd'와 같은 출력이 표시됩니다. 콘솔을 만들지 않으면 출력을 얻지 못합니다. stdout은 기본적으로 콘솔에 표시되지만 콘솔에 표시된 모든 내용이 stdout을 통해 전달된다는 의미는 아닙니다. – Luaan

+0

@Varro C#의 해당 기능은 예를 들어'Console.CursorTop = 0'을 실행할 때와 같습니다. stdout 대신 콘솔 버퍼에 다시 쓰십시오.이제는 인프라가 똑똑해서 출력을 stdout *으로 가져올 수는 있지만 간단히 변경할 수있는 것이 없습니다. stdout에는 "되감기"기능이 없습니다. 단지 스트림 일뿐입니다. – Luaan

관련 문제