2015-10-29 21 views
1

我正在製作一個應用程序,它將產生一個具有命令行解釋器的進程。我需要從另一臺機器向這個CLI提供命令。現在,我必須檢測命令何時完成,因此我正在檢查CLI提示何時出現在我產生的進程的標準輸出中。這裏有一段代碼:爲什麼OutputDataReceived不會爲提示而引發,從而阻止AutoResetEvent發出信號?

private string StartProcess(string input) 
{ 
try 
{ 
    StringBuilder output = new StringBuilder(); 
    StringBuilder error = new StringBuilder(); 

    AutoResetEvent commandFinished = new AutoResetEvent(false); 

    ProcessStartInfo startInfo = new ProcessStartInfo() 
    { 
     FileName = "myprocess.exe", 
     Arguments = "", 
     UseShellExecute = false, 
     CreateNoWindow = true, 
     RedirectStandardOutput = true, 
     RedirectStandardError = true, 
     RedirectStandardInput = true, 
     UserName = System.Environment.UserName 
    }; 

    Process myProcess = new Process() 
    { 
     StartInfo = startInfo, 
     EnableRaisingEvents = true 
    }; 

    myProcess.OutputDataReceived += new DataReceivedEventHandler((sender, e) => 
    { 
     if (e.Data != null) 
     { 
      string prompt = "user >"; 

      if (e.Data.Substring(e.Data.Length - prompt.Length).Equals(prompt)) 
      { 
       Console.WriteLine("Received prompt! Sending CommandFinished signal!"); 
       commandFinished.Set(); 
       Console.WriteLine("CommandFinished signal set!"); 
      } 
      else 
      { 
       output.AppendLine(e.Data); 
      } 
     } 
     else 
     { 
      // Data finished 
      Console.WriteLine("StdOut data finished! Sending CommandFinished signal!"); 
      commandFinished.Set(); 
      Console.WriteLine("CommandFinished signal set!"); 
     } 
    }); 


    myProcess.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => 
    { 
     if (e.Data != null) 
     { 
      Console.WriteLine("Error Data received: " + e.Data.ToString()); 
      error.AppendLine(e.Data); 
     } 
    }); 

    myProcess.Start(); 
    myProcess.BeginOutputReadLine(); 
    myProcess.BeginErrorReadLine(); 

    Console.WriteLine("Executing input command: " + input); 
    myProcess.StandardInput.WriteLine(input); 

    Console.WriteLine("Waiting for input command to complete..."); 

    commandFinished.WaitOne(); 

    Console.WriteLine("Command complete!"); 

    return output.ToString(); 
} 
catch (Exception ex) 
{ 
    Console.WriteLine("EXCEPTION: " + ex.ToString()); 
    throw ex; 
} 
} 

現在,代碼掛在對WaitOne()的調用上。我很困惑,爲什麼 - 我沒有在輸出中檢測到CLI提示符,並且我從來沒有得到任何WriteLines告訴我在OutputDataReceived事件中收到提示,或收到的數據爲空。即當前一個命令完成並且顯示提示時,OutputDataReceived事件不會引發。

我提供的輸入命令確實需要一段時間,但確實完成了。我在這裏使用AutoResetEvent錯誤嗎?

+0

您是否確認通風管理器正在被調用?如果我不得不猜測,我敢打賭問題是輸出數據末尾還有其他內容,比如空格,或者提示符被分割爲多個DataReceived事件(可能是「用戶」和一個對於「>」)。 –

+0

您還需要處理'e.Data.Length - prompt.Length'小於0 –

+0

@DarkFalcon,我實際上捕獲輸出,如果我沒有得到提示,所以我應該看到提示(或部分如果是這樣的話,我只能看到輸出的前幾行,然後掛起。 – Tino

回答

2

如果沒有a good, minimal, complete code example無法確切知道代碼可能存在什麼問題。但是我可以看到一個明顯的解釋:

OutputDataReceived事件發生在每個收到的輸出。也就是說,一個以換行符結尾的字符串。

沒有關於您的外部過程的細節,我不能肯定地說。但是大多數CLI類型的情況涉及顯示而沒有換行符。即提示將被寫入控制檯,並且用戶輸入預計會在提示符後立即響應到控制檯,而不是在下一行。

如果您的情況屬於這種情況,那麼您幾乎可以肯定無法檢測到提示,因爲事件不會針對提示單獨提出。在上一個命令操作的最後一行輸出之後,下一次事件將在之後通過標準輸入發送到進程。這對於知道何時發送該命令來說顯然太晚了。 :)

爲了得到這個工作,你必須通過而不是基於行的其他機制之一讀取過程中的輸入。

+0

事實上,OutputDataReceived事件只會在行上產生,這是個問題。謝謝! – Tino

相關問題