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

在Unity中,我们可能需要自己写Editor工具。有时候我们可能还需要执行外部指令或者脚本(比如python脚本),这个时候,就需要用c#的System.Diagnostics.Process这个类了。

 

命名空间

using System.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

 

posted @ 2020-12-15 13:05  韩梦芫  阅读(2598)  评论(0编辑  收藏  举报