目的: 为了不干扰或者阻塞主线程

Unity中使用Process类来开启进程

Process类:

  启动和停止进程, 获取或设置进程优先级, 是否已经退出, 以及获取系统正在运行的所有进行列表和各进程资源占用情况。

入参arguments: 控制台需要输入的命令行

文件名FileName : 传入exe绝对路径,关于unity路径问题最好规范点,统一使用'/'

private void CallCmd(string arguments)
        {
            Encoding GBK = Encoding.GetEncoding(936);

            try
            {
                Process process = new Process();
                process.StartInfo.FileName = m_StreamingAssertExePath;
                process.StartInfo.Arguments = arguments;
                process.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                process.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                process.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                process.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                process.StartInfo.StandardOutputEncoding = GBK;
                process.StartInfo.CreateNoWindow = true;//不显示程序窗口
                process.Start();//启动程序

                process.OutputDataReceived += (s, _e) =>
                {
                    UnityEngine.Debug.Log(GBK2UTF8(_e.Data));
                };
                process.ErrorDataReceived += (s, _e) =>
                {
                    UnityEngine.Debug.Log(GBK2UTF8(_e.Data));
                };

                process.EnableRaisingEvents = true;
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                process.WaitForExit();
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError(e.Message);
            }
        }

        public static string GBK2UTF8(string value)
        {
            Encoding GBK = Encoding.GetEncoding(936);
            byte[] bytes = Encoding.Convert(GBK, Encoding.UTF8, GBK.GetBytes(value));
            return Encoding.UTF8.GetString(bytes);
        }

直接调用CallCmd的话,会发现还是会阻塞主线程, 把process执行完才会执行主线程.

所以要把此函数放到子线程里去执行,*.exe没有做死循环或者阻碍线程运行的操作,所以在子线程调用结束会等待自动回收的.所以没必要Abort().

这里是自己写的保存一张照片命令行

public void Send_GetPicture()
        {
            if (!HasCmdExe) return;
            Thread thread = new Thread(new ThreadStart(exe_Picture));
            thread.Start();
        }

        private void exe_Picture()
        {
            string instructions = string.Format("{0},{1},{2}", (int)CmdSelect.Capture, 0, m_URL);
            CallCmd(instructions);
        }

控制台应用(.NET Framework)项目

unity job 调试 unity的控制台怎么调出来_unity job 调试

这里注意控制台使用Console.ReadLine输入指令,unity调用是通过args输入

尽量不要去做阻碍程序运行的操作,比如文末注释掉的Console.ReadKey();

如果加了这行,unity是不会停止子线程的,需要手动把控制台进程杀掉(Process.kill) 以及中止子线程(Abort)

static void Main(string[] args)
        {
            Console.Write(@"
--------------------------模式选择--------------------------------
<0> - 上传设备信息    <!-- 0 -->,<!-- Custom -->,<!-- URL -->
<1> -   上传日志      <!-- 1 -->,<!-- Custom -->,<!-- URL -->,<!-- LogPath -->
<2> - 获取当前照片    <!-- 2 -->,<!-- Custom -->,<!-- URL -->
请输入指令: ");
            string readLine = string.Empty;
#if DEBUG
            readLine = Console.ReadLine().Trim();
#else
            if (args.Length <=0)
            {
                return;
            }
            readLine = args[0].Trim();
#endif
            string[] analysis = readLine.Split(',');
            //上传设备信息
            if (analysis.Length == 3 && Convert.ToInt32(analysis[0]) == 0)
            {
                //TODO: 获取系统配置并提交至服务器
            }
            //上传日志
            else if (analysis.Length == 4 && Convert.ToInt32(analysis[0]) == 1)
            {
               //TODO: 获取unity的日志并提交至服务器
               //我这里是由unity保存log日志,写入StreamingAssert/yyyy_MM_dd_HH_mm_ss.log,
               //命令行传入路径,这里读取数据流上传服务器
            }
            //获取当前照片
            else if (analysis.Length == 3 && Convert.ToInt32(analysis[0]) == 2)
            {
                //TODO: 拍摄一张照片并提交至服务器
            }
            else
            {
                Console.WriteLine("ErrorCode:{0} Message:{1}", (int)SystemCode.Error, "未知错误!");
            }
            //Console.WriteLine("--------------------------任意键退出--------------------------");
            //Console.ReadKey();
        }

关于生成有个小技巧:

一般我们的控制台项目会应用第三方库(FFmpeg,Aforge,LitJson,OpenCV等等), 生成exe的时候这些*.dll也会随之生成在同级目录下, 使用Costura.Fody将源代码合并到exe里面, 生成结束, 把exe拉取到任意目录都可以运行.

通过NuGet管理导入Costura.Fody

unity job 调试 unity的控制台怎么调出来_服务器_02