【Process】方法中的相关异常汇总

Process类中各类方法异常情况汇总

一. ExitCode()方法使用带来的问题

先看下面一段代码,这是一个正常用于调用外部可执行程序的代码类,其中,有一个唯一的int类型的返回输出值,这个值会返回调用外部可执行程序之后的return code信息,MyApp类中通过定义一个_process_Exited方法,透过autoEvent 等待的方式来监控程序的退出,一旦process的Exited 行为触发,则会执行_process_Exited方法里面的Set()中断前面的等待行为

// Sample Code 1
internal class MyApp
    {
        private StringBuilder mResult = new StringBuilder();

        private object mObject = new object();

        private static AutoResetEvent autoEvent = new AutoResetEvent(false);

        internal string GetExecResult(string ExeName, string Param, out int exitcode)
        {
            exitcode = -1;
            MyProcess.autoEvent.Reset();
            this.mResult.Clear();
            Process process = new Process();
            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(ExeName);
            process.StartInfo.FileName = ExeName;
            process.StartInfo.Arguments = Param;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.EnableRaisingEvents = true;
            process.Exited += new EventHandler(this._process_Exited);
            process.OutputDataReceived += new DataReceivedEventHandler(this._process_OutputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(this._process_ErrorDataReceived);
            process.Start();
            process.BeginOutputReadLine();
            MyProcess.autoEvent.WaitOne();
            MyProcess.autoEvent.Reset();
            exitcode = process.ExitCode;
            return this.mResult.ToString();
        }

        private void _process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
        }

        private void _process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(e.Data))
            {
                this.mResult.AppendLine(e.Data);
            }
        }

        private void _process_Exited(object sender, EventArgs e)
        {
            MyProcess.autoEvent.Set();
        }

而此时,再去获取process的exit code是不是能获取到呢,好像可以,但实际却会出现如下异常
“Process must exit before requested information can be determined”
这个异常代表了前面的Process虽然Exited 行为触发了,流程上虽然看似没有问题,但是这里涉及到
进程在系统中的相关资源退出问题,这种无法预期时间的流程就会造成上述问题
那对于上述问题,有一个比较简单的处理方法,目前亲测有效

        internal string GetExecResult(string ExeName, string Param, out int exitcode)
        {
            exitcode = -1;
            MyProcess.autoEvent.Reset();
            this.mResult.Clear();
            Process process = new Process();
            process.StartInfo.WorkingDirectory = Path.GetDirectoryName(ExeName);
            process.StartInfo.FileName = ExeName;
            process.StartInfo.Arguments = Param;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.EnableRaisingEvents = true;
            process.Exited += new EventHandler(this._process_Exited);
            process.OutputDataReceived += new DataReceivedEventHandler(this._process_OutputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(this._process_ErrorDataReceived);
            process.Start();
            process.BeginOutputReadLine();
            MyProcess.autoEvent.WaitOne();
            MyProcess.autoEvent.Reset();
            process.WaitForExit();
            exitcode = process.ExitCode;
            return this.mResult.ToString();
        }

如上,调用process.WaitForExit()方法,MSDN类方法中对于这方法有一个清晰的描述,

        // Summary:
        //     Instructs the System.Diagnostics.Process component to wait indefinitely for
        //     the associated process to exit.

此方法会等待所有相关的process退出,这样可以保证process是真正意义上的退出,从而避免上面异常的发生

更于2021/12/28

上一篇:菜鸟Linux 磁盘管理


下一篇:docker删除容器 镜像