1. 程式人生 > 實用技巧 >Unity中C#如何執行cmd命令(System.Diagnostics.Process的使用)

Unity中C#如何執行cmd命令(System.Diagnostics.Process的使用)

在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