親愛的同學們,你們知道怎麼在一個Win32 Console Application中同時打印中日韓新馬泰非洲列國文字么?
反正我是不會╮(╯-╰)╭ 但是用GUI Application來做是很容易的。本來想移植putty中的終端模擬器,但是純C啊,實力有限233
我們要求不高,只要能打印東西就行了。至於輸入啊,信號啊什麼的,再說嘛~
完整代碼可在https://github.com/fffonion/MAClient/blob/gui/frmNiceTerm.cs 獲得
首先,用Process類啟動一個進程:
1 2 3 4 5 6 7 8 9 10 11 |
process = new Process(); process.StartInfo.FileName = "ping"; process.StartInfo.Arguments = "127.0.0.1"; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true;//重定向stdout process.StartInfo.RedirectStandardInput = true;//重定向stdin process.StartInfo.RedirectStandardError = true;//重定向stderr process.StartInfo.EnvironmentVariables["NICE_TERM"] = "1";//export環境變量 process.StartInfo.StandardOutputEncoding = Encoding.UTF8;//設置輸出流編碼 process.StartInfo.CreateNoWindow = true;//不顯示窗口 process.Start(); |
之所以加一個環境變量,是因為這樣我們就可以在程序中判斷是否使用了這個NiceTerm
我們在界面里拖進一個richTextBox,然後
1 2 3 4 5 6 |
while(true) { String line=null; while ((line =process.StartInfo.StandardOutput.ReadLine()) != null) richTextBox1.AppendText(line+"\n"); richTextBox1.ScrollToCaret(); }; |
然後我們運行一下,發現跑得很好,基本和cmd里是一個效果。
但是這樣做是有問題的。首先我們在主線程里使用了一個死循環,這習慣不好;再者,其實process.StartInfo.StandardOutput是一個StreamReader,讀取是同步的而且有超時,也就是說,一定時間內沒有stdout出來,它就是hang在那裡不動了。
我們可以嘗試將process.StartInfo.FileName = “python.exe”;讓它運行一個每隔2秒print一次的腳本,你會發現卧槽整個程序都無響應了233
參考這個項目Embedding a Console in a C# Application – CodeProject之後,用backgroundWorker解決了這個問題。由於用this.outputWorker.RunWorkerAsync(); 包裝了讀取stdout的過程,因此讀取工作就是異步的了,也就不會hang住了。
附上運行效果圖:
接下去要研究下怎麼發送Ctrl+C給process,以及處理stdin