Unity中C#如何執行cmd命令(System.Diagnostics.Process的使用)
阿新 • • 發佈:2020-12-15
在Unity中,我們可能需要自己寫Editor工具。有時候我們可能還需要執行外部指令或者指令碼(比如python指令碼),這個時候,就需要用c#的System.Diagnostics.Process這個類了。
名稱空間
usingSystem.Diagnostics;
Process.Star()的構造方法
名稱 | 說明 |
---|---|
Process.Start () | 啟動(或重用)此 Process 元件的StartInfo屬性指定的程序資源,並將其與該元件關聯。 |
Process.Start (ProcessStartInfo) | 啟動由包含程序啟動資訊(例如,要啟動的程序的檔名)的引數指定的程序資源,並將該資源與新的 Process 元件關聯。 |
Process.Start (String) | 通過指定文件或應用程式檔案的名稱來啟動程序資源,並將資源與新的 Process 元件關聯。 |
Process.Start (String, String) | 通過指定應用程式的名稱和一組命令列引數來啟動一個程序資源,並將該資源與新的 Process 元件相關聯。 |
Process.Start (String, String, SecureString, String) | 通過指定應用程式的名稱、使用者名稱、密碼和域來啟動一個程序資源,並將該資源與新的 Process 元件關聯起來。 |
Process.Start (String, String, String, SecureString, String) | 通過指定應用程式的名稱和一組命令列引數、使用者名稱、密碼和域來啟動一個程序資源,並將該資源與新的 Process 元件關聯起來。 |
簡單的介面封裝
public static void RunCmd(string cmd, string args, string workdir=null) { string[] res = new string[2]; var p = CreateCmdProcess (cmd, args, workdir); res [0] = p.StandardOutput.ReadToEnd (); res [1] = p.StandardError.ReadToEnd (); p.Close ();return res; } public static System.Diagnostics.Process CreateCmdProcess(string cmd, string args, string workdir=null) { var pStartInfo = new System.Diagnostics.ProcessStartInfo (cmd); pStartInfo.Arguments = args; pStartInfo.CreateNoWindow = false; pStartInfo.UseShellExecute = false; pStartInfo.RedirectStandardError = true; pStartInfo.RedirectStandardInput = true; pStartInfo.RedirectStandardOutput = true; pStartInfo.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8; pStartInfo.StandardOutputEncoding= System.Text.UTF8Encoding.UTF8; if(!string.IsNullOrEmpty(workdir)) pStartInfo.WorkingDirectory = workdir; return System.Diagnostics.Process.Start(pStartInfo); }
呼叫,假設我們想執行svn update的指令
var path = "D:\\Project\\"; RunCmd ("svn", string.Format("update \"{0}\"", path));
關於WorkingDirectory屬性
WorkingDirectory屬性指定可執行檔案的位置。
如果WorkingDirectory是空字串,則認為當前目錄以包含可執行檔案。
假設我們有一個py指令碼test.py在D盤的py_pro目錄中,即 D:\\py_pro\\test.py
我們要執行這個指令碼,需要這樣子
var workdir= "D:\\py_pro\\"; RunCmd ("python", workdir + "test.py", workdir);
// 開啟記事本 System.Diagnostics.Process.Start("notepad.exe"); // 開啟計算器 System.Diagnostics.Process.Start("calc.exe "); // 開啟登錄檔 System.Diagnostics.Process.Start("regedit.exe "); // 開啟畫圖板 System.Diagnostics.Process.Start("mspaint.exe "); //開啟寫字板 System.Diagnostics.Process.Start("write.exe "); // 開啟播放器 System.Diagnostics.Process.Start("mplayer2.exe "); // 開啟工作管理員 System.Diagnostics.Process.Start("taskmgr.exe "); // 開啟事件檢視器 System.Diagnostics.Process.Start("eventvwr.exe "); // 開啟系統資訊 System.Diagnostics.Process.Start("winmsd.exe "); // 開啟Windows版本資訊 System.Diagnostics.Process.Start("winver.exe "); // 發郵件 System.Diagnostics.Process.Start("mailto: "+ address);
介面封裝(詳細版):
using System; using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.IO; using System.Threading; using System.Text; class EdtUtil { /// <summary> /// 構建Process物件,並執行 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="workingDri">工作目錄</param> /// <returns>Process物件</returns> private static System.Diagnostics.Process CreateCmdProcess(string cmd, string args, string workingDir = "") { var en = System.Text.UTF8Encoding.UTF8; if (Application.platform == RuntimePlatform.WindowsEditor) en = System.Text.Encoding.GetEncoding("gb2312"); var pStartInfo = new System.Diagnostics.ProcessStartInfo(cmd); pStartInfo.Arguments = args; pStartInfo.CreateNoWindow = false; pStartInfo.UseShellExecute = false; pStartInfo.RedirectStandardError = true; pStartInfo.RedirectStandardInput = true; pStartInfo.RedirectStandardOutput = true; pStartInfo.StandardErrorEncoding = en; pStartInfo.StandardOutputEncoding = en; if (!string.IsNullOrEmpty(workingDir)) pStartInfo.WorkingDirectory = workingDir; return System.Diagnostics.Process.Start(pStartInfo); } /// <summary> /// 執行命令,不返回stderr版本 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="workingDri">工作目錄</param> /// <returns>命令的stdout輸出</returns> public static string RunCmdNoErr(string cmd, string args, string workingDri = "") { var p = CreateCmdProcess(cmd, args, workingDri); var res = p.StandardOutput.ReadToEnd(); p.Close(); return res; } /// <summary> /// 執行命令,不返回stderr版本 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="input">StandardInput</param> /// <param name="workingDri">工作目錄</param> /// <returns>命令的stdout輸出</returns> public static string RunCmdNoErr(string cmd, string args, string[] input, string workingDri = "") { var p = CreateCmdProcess(cmd, args, workingDri); if (input != null && input.Length > 0) { for (int i = 0; i < input.Length; i++) p.StandardInput.WriteLine(input[i]); } var res = p.StandardOutput.ReadToEnd(); p.Close(); return res; } /// <summary> /// 執行命令 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <returns>string[] res[0]命令的stdout輸出, res[1]命令的stderr輸出</returns> public static string[] RunCmd(string cmd, string args, string workingDir = "") { string[] res = new string[2]; var p = CreateCmdProcess(cmd, args, workingDir); res[0] = p.StandardOutput.ReadToEnd(); res[1] = p.StandardError.ReadToEnd(); #if !UNITY_IOS res[2] = p.ExitCode.ToString(); #endif p.Close(); return res; } /// <summary> /// 開啟資料夾 /// </summary> /// <param name="absPath">資料夾的絕對路徑</param> public static void OpenFolderInExplorer(string absPath) { if (Application.platform == RuntimePlatform.WindowsEditor) RunCmdNoErr("explorer.exe", absPath); else if (Application.platform == RuntimePlatform.OSXEditor) RunCmdNoErr("open", absPath.Replace("\\", "/")); } }
介面封裝(詳細版):
using System; using UnityEditor; using UnityEngine; using System.Collections.Generic; using System.IO; using System.Threading; using System.Text; class EdtUtil { /// <summary> /// 構建Process物件,並執行 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="workingDri">工作目錄</param> /// <returns>Process物件</returns> private static System.Diagnostics.Process CreateCmdProcess(string cmd, string args, string workingDir = "") { var en = System.Text.UTF8Encoding.UTF8; if (Application.platform == RuntimePlatform.WindowsEditor) en = System.Text.Encoding.GetEncoding("gb2312"); var pStartInfo = new System.Diagnostics.ProcessStartInfo(cmd); pStartInfo.Arguments = args; pStartInfo.CreateNoWindow = false; pStartInfo.UseShellExecute = false; pStartInfo.RedirectStandardError = true; pStartInfo.RedirectStandardInput = true; pStartInfo.RedirectStandardOutput = true; pStartInfo.StandardErrorEncoding = en; pStartInfo.StandardOutputEncoding = en; if (!string.IsNullOrEmpty(workingDir)) pStartInfo.WorkingDirectory = workingDir; return System.Diagnostics.Process.Start(pStartInfo); } /// <summary> /// 執行命令,不返回stderr版本 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="workingDri">工作目錄</param> /// <returns>命令的stdout輸出</returns> public static string RunCmdNoErr(string cmd, string args, string workingDri = "") { var p = CreateCmdProcess(cmd, args, workingDri); var res = p.StandardOutput.ReadToEnd(); p.Close(); return res; } /// <summary> /// 執行命令,不返回stderr版本 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <param name="input">StandardInput</param> /// <param name="workingDri">工作目錄</param> /// <returns>命令的stdout輸出</returns> public static string RunCmdNoErr(string cmd, string args, string[] input, string workingDri = "") { var p = CreateCmdProcess(cmd, args, workingDri); if (input != null && input.Length > 0) { for (int i = 0; i < input.Length; i++) p.StandardInput.WriteLine(input[i]); } var res = p.StandardOutput.ReadToEnd(); p.Close(); return res; } /// <summary> /// 執行命令 /// </summary> /// <param name="cmd">命令</param> /// <param name="args">命令的引數</param> /// <returns>string[] res[0]命令的stdout輸出, res[1]命令的stderr輸出</returns> public static string[] RunCmd(string cmd, string args, string workingDir = "") { string[] res = new string[2]; var p = CreateCmdProcess(cmd, args, workingDir); res[0] = p.StandardOutput.ReadToEnd(); res[1] = p.StandardError.ReadToEnd(); #if !UNITY_IOS res[2] = p.ExitCode.ToString(); #endif p.Close(); return res; } /// <summary> /// 開啟資料夾 /// </summary> /// <param name="absPath">資料夾的絕對路徑</param> public static void OpenFolderInExplorer(string absPath) { if (Application.platform == RuntimePlatform.WindowsEditor) RunCmdNoErr("explorer.exe", absPath); else if (Application.platform == RuntimePlatform.OSXEditor) RunCmdNoErr("open", absPath.Replace("\\", "/")); } }
使用
上面的RunCmd介面,return的string[],第0個是指令碼的輸出,第1個是錯誤輸出
比如通過上面的RunCmd介面執行下面的python指令碼
#python指令碼: test.py, 放在Assets/python目錄中 print("Hello, I am python!") print("This is a test") try: print(1/0) except BaseException,e: print("Error: " + str(e)) //c# 通過RunCmd介面執行python指令碼 var workdir = Application.dataPath + "/python/"; var results = EdtUtil.RunCmd("python", workdir + "test.py", workdir); Debug.Log("python output: " + results[0]); Debug.Log("python error: " + results[1]);
輸出的結果是
python output: Hello, I am python! This is a test python error: Error: integer division or module by zero