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