在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 组件关联起来。
using System;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Text;
class EdtUtil
{
///
/// 构建Process对象,并执行
///
/// 命令
/// 命令的参数
/// 工作目录
/// Process对象
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);
}
///
/// 运行命令,不返回stderr版本
///
/// 命令
/// 命令的参数
/// 工作目录
/// 命令的stdout输出
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;
}
///
/// 运行命令,不返回stderr版本
///
/// 命令
/// 命令的参数
/// StandardInput
/// 工作目录
/// 命令的stdout输出
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;
}
///
/// 运行命令
///
/// 命令
/// 命令的参数
/// string[] res[0]命令的stdout输出, res[1]命令的stderr输出
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();
p.Close();
return res;
}
///
/// 打开文件夹
///
/// 文件夹的绝对路径
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
我们可以在c#根据python返回的结果进行判断然后抛出c#的异常:
// c#抛出异常
if(results[0].LastIndexOf("Error") > 0)
{
throw new System.Exception("python Error");
}