2012-02-29 5 views
1

cmd.exe의 입력과 출력을 텍스트 상자로 리디렉션하여 콘솔을 에뮬레이션하는 Windows 응용 프로그램을 작성했습니다. 시작 코드는 다음과 같습니다 : 콘솔 입력 리디렉션

StreamWriter inputWriter; 
StreamReader outputReader; 
StreamReader errorReader; 
Process proc = new Process(); 
byte[] outputBuffer = new byte[1024]; 
byte[] errorBuffer = new byte[1024]; 

proc.StartInfo.FileName = "cmd.exe"; 
proc.StartInfo.FileName = "cmd.exe"; 
proc.StartInfo.Arguments = "/Q"; 
proc.StartInfo.UseShellExecute = false; 
proc.StartInfo.ErrorDialog = false; 
proc.StartInfo.RedirectStandardError = true; 
proc.StartInfo.RedirectStandardInput = true; 
proc.StartInfo.RedirectStandardOutput = true; 
proc.StartInfo.CreateNoWindow = true; 
proc.Start(); 
inputWriter = proc.StandardInput; 
outputReader = proc.StandardOutput; 
errorReader = proc.StandardError; 
outputReader.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, ShowOutput, null); 
errorReader.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, ShowError, null);proc.StartInfo.Arguments = "/Q"; 
proc.StartInfo.UseShellExecute = false; 
proc.StartInfo.ErrorDialog = false; 
proc.StartInfo.RedirectStandardError = true; 
proc.StartInfo.RedirectStandardInput = true; 
proc.StartInfo.RedirectStandardOutput = true; 
proc.StartInfo.CreateNoWindow = true; 
proc.Start(); 
inputWriter = proc.StandardInput; 
outputReader = proc.StandardOutput; 
errorReader = proc.StandardError; 
outputReader.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, ShowOutput, null); 
errorReader.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, ShowError, null); 

내가 콘솔 출력을 읽을 수 있으며, 입력 스트림에 작성하여 여기에 명령을 보낼 수 오전 사전 처리를 시작

.

이 방법으로 일부 응용 프로그램을 시작하면 해당 응용 프로그램의 출력도 리디렉션되고 모든 것이 제대로 작동하지만 응용 프로그램이 입력 스트림에 기록되는 데이터를 수신하지 않는 것처럼 보입니다. 일부 콘솔 명령조차도 입력을받을 수 없습니다. 예 : 내가 inputWriter.WriteLine("del *.log");을 호출하면 "Are you sure"프롬프트가 표시되지만 inputWriter.Write("y");을 호출하면 "y"는 콘솔에 의해 반향되지만 아무런 반응이 없으면 콘솔은 입력을 기다립니다. inputWriter.WriteLine("pause"); 콘솔을 호출하면 inputWriter.Write(" "); 이후에 콘솔이 일시 중지되고 계속해야합니다.

여기의 문제는 무엇이며 입력을 콘솔과 그 내부에서 실행되는 응용 프로그램 (및 명령)으로 올바르게 리디렉션 할 수 있습니까?

미리 감사드립니다.

건배!

답변

2

이것은 흥미로운 문제점으로, win32 명령 인터프리터가 보안상의 이유로 입력을 처리하는 방식과 관련이 있습니다. this one과 같이 문제를 해결 한 몇 가지 프로젝트가 있습니다 (주로). 입력 제한을 극복하기 위해 구현해야 할 트릭이 있는지 알아보기 위해 코드를 살펴볼 수도 있습니다 (실제로 비난하는 경우).

나는 C#으로 작성된 전체 콘솔 대체 솔루션을 본 적이 없다고 생각합니다.

+1

콘솔 대체품에 가장 가까운 생각은 POSH 콘솔입니다. 그리고 네, 세부 사항을 모르겠지만 콘솔 프로그래밍은 어설프고 Powershell도 Windows 콘솔 작동 방식 때문에 몇 가지 제한이 있습니다. –

1

나는 여러 번 이것을했다. 이 문제는 프로그램이 단일 스레드이기 때문에 발생합니다. 프로세스 asyc를 실행해야합니다. 여기에 exemample 있습니다.

private void exportButton_Click(object sender, EventArgs e) 
    { 
     System.Diagnostics.Process p = new System.Diagnostics.Process(); 

     p.StartInfo.FileName = "cmd.exe"; 
     p.StartInfo.Arguments = ""; 
     p.StartInfo.RedirectStandardOutput = true; 
     p.StartInfo.RedirectStandardInput = true; 
     p.StartInfo.UseShellExecute = false; 
     p.StartInfo.CreateNoWindow = true; 

     p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(ConsoleOutputHandler); 

     p.Start(); 
     p.BeginOutputReadLine(); 

     //p.WaitForExit(); 
     //p.Dispose(); 
    } 

    private void UpdateTextBox(String message) 
    { 
     if (consoleOutputBox.InvokeRequired) 
     { 
      UpdateConsoleWindowDelegate update = new UpdateConsoleWindowDelegate(UpdateTextBox); 
      consoleOutputBox.BeginInvoke(update, message); 
     } 
     else 
     { 
      consoleOutputBox.AppendText(message); 
     } 
    } 

    void ConsoleOutputHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs recieved) 
    { 
     if (!String.IsNullOrEmpty(recieved.Data)) 
     { 
      UpdateTextBox(recieved.Data + "\n"); 
     } 
    } 
+0

사실 출력 스트림에서 BeginRead를 사용하여 id 비동기로 만들었습니다. 입력 스트림에 쓰는 것은 콘솔 (또는 콘솔에서 실행중인 프로그램)이 입력을 기다리고있을 때 문제를 일으 킵니다. dir, cd 등의 명령을 실행할 수 있지만 일단 프롬프트가 필요하면 (예 : y/n) 콘솔이 입력 스트림에 기록 된 문자에 응답하지 않습니다. 어떻게 든 콘솔에 의해 실행 된 프로세스를 찾은 다음 그 프로세스의 입력 스트림에 기록해야합니다. – 0wl