1. 程式人生 > >C#使用cmd執行.exe檔案,並在程式關閉時關閉開啟的程序

C#使用cmd執行.exe檔案,並在程式關閉時關閉開啟的程序

本來是參考網上的來自酷小孩的一段程式碼(博主吐槽非常正確),如下:

       string str = Console.ReadLine();

       System.Diagnostics.Process p = new System.Diagnostics.Process();
       p.StartInfo.FileName = "cmd.exe";
       p.StartInfo.UseShellExecute = false;    //是否使用作業系統shell啟動
       p.StartInfo.RedirectStandardInput = true;//接受來自呼叫程式的輸入資訊
       p.StartInfo.RedirectStandardOutput = true;//由呼叫程式獲取輸出資訊
       p.StartInfo.RedirectStandardError = true;//重定向標準錯誤輸出
       p.StartInfo.CreateNoWindow = true;//不顯示程式視窗
       p.Start();//啟動程式

       //向cmd視窗傳送輸入資訊
       p.StandardInput.WriteLine(str + "&exit");
       p.StandardInput.AutoFlush = true;

       //獲取cmd視窗的輸出資訊,在執行這一行後C#呼叫了.exe檔案執行
       string output = p.StandardOutput.ReadToEnd();

       p.WaitForExit();//等待程式執行完退出程序
       p.Close();
       Console.WriteLine(output);

       直接使用這段程式碼進行多行命令列執行時會出現這麼一個問題:可能執行了幾行之後就停止了,具體原因沒有找到,但是通過國外網友提供的一個官方文件的例子中對程式碼進行修改後可以正常執行,網址如下:https://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardinput.aspx
        為了進行對比我將程式碼註釋進行了一定量的刪除,先介紹我的需求情況:需要使用命令列呼叫一個.exe程式對多個視訊進行處理,由於視訊路徑比較長,視訊數量大導致文字長度超過了cmd一次輸入文字的長度,因此需要分成多行輸入處理,暫時不需要回顯cmd的輸出,將程式碼更改如下:

            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;    //是否使用作業系統shell啟動
            p.StartInfo.RedirectStandardInput = true;//接受來自呼叫程式的輸入資訊
            p.StartInfo.RedirectStandardOutput = false;//不需要獲取輸出資訊
            p.StartInfo.RedirectStandardError = true;//不需要重定向標準錯誤輸出,但false時下面的指令未執行
            p.StartInfo.CreateNoWindow = true;//不顯示程式視窗
            p.Start();//啟動程式
            StreamWriter mySR = p.StandardInput;
            //向cmd視窗傳送輸入資訊
            for (int nowIdx = 0; nowIdx < videos.Length; nowIdx++)
            {
                //str表示一行命令
                mySR.WriteLine(str);
                //這裡的Flush()操作和我理解的不一樣,儘管flush了但是命令列並沒有立即執行
                //而且當需要執行的命令列數量十分多的時候,在使用了WriteLine後會在隨機行數之後值執行,可能與緩衝區大小有關
                mySR.Flush();
            }
            //這個地方我對於原文所提供的exit和&exit的區別沒有完全弄清,以後可能進行補充
            p.StandardInput.WriteLine("&exit");
            //關閉StreamWriter後,之前輸入的命令列會立即執行
            mySR.Close();
            p.WaitForExit();
            p.Close();

    這裡這麼寫會遇到一個問題,有些程式是不會自己停止的,亦或者在啟動了該程式之後需要執行其他的程式碼,這個時候如果使用Process.WaitForExit()會使程式陷入迴圈(若是會自動結束,則會在結束後執行後面的程式碼)。因此需要做出一點改變,我是在C# WinForm程式中使用的,因此可以在Form窗體退出時結束程式。

#重寫並繫結視窗退出事件
protected override void OnClosing(CancelEventArgs e)
        {
            #將p定義為public static變數,可以在其他檔案中呼叫
            if(nameSpace.p != null)
            {
                #獲取程序並關閉
                Process[] pro = Process.GetProcessesByName("開啟的程序的名字");
                pro[0].Kill();
            }
            base.OnClosing(e);
        }