检查进程是否返回错误 | C#

9

在声明并启动进程如下后:

System.Diagnostics.Process _p = new System.Diagnostics.Process();
.....
.....
....
_p.Start();

现在有两种可能性:要么是输出,要么是错误。
如果发生错误,是否有Process类的任何属性可以知道是否发生了错误?
我正在重定向标准输出,我不想重定向标准错误如MSDN所警告的那样。另外我也不想使用:BeginOutputReadLine(); 有其他替代方法吗?
谢谢。

4
您要启动的进程是否返回正确的退出代码(例如成功为0,错误为1)?如果是这样的话,在进程退出后,您可以检查_p.ExitCode - Cᴏʀʏ
@Cory 非常感谢。我之前启动的自定义进程没有任何退出码。但现在我已经实施了这些,并检查了 _p.ExitCode,一切都运行得非常完美。再次感谢你。 - R.C
你说你不想重定向标准错误输出,就像MSDN中所警告的那样(http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandarderror.aspx),也许是我的英语理解能力有问题,但我没有看到文章中任何警告你不要重定向标准错误输出的地方,只是告诉你如何防止死锁。 - Jason
是的,你说得对,Jason。在这里,我不知道我的进程是否会成功运行或出现错误,同时我也不想使用Beginoutputreadline(),因为它被提到要避免死锁。我需要的是:只有当发生错误时,我才想读取标准错误,否则读取标准输出。 - R.C
2个回答

13

我有一个需要启动进程并等待它们退出的服务,我使用类似以下代码:

process.Start();
int timeout = ... // some normal value in milliseconds

process.WaitForExit(timeout);

try
{
   //ExitCode throws if the process is hanging
   return (CommandErrorCode)process.ExitCode;
}
catch (InvalidOperationException ioex)
{
   return CommandErrorCode.InternalError;
}

CommandErrorCode 是类似于以下内容的东西

public enum CommandErrorCode
{
    Success = 0,
    //some other values I know from the processes that are managed
    InternalError = 256 // the ExitCode is a byte, so this out of that range
}

顺便提一下,我重定向了标准输出和标准错误,并使用 BeginXXXReadLine 和 XXXDataReceived 处理程序,但是我使用的进程是已知、定义良好且表现良好的。


在上面的try块中,您提到如果进程挂起,将抛出ExitCode。难道不是只有当进程退出而不是挂起时才会抛出ExitCode吗?请纠正我,因为我不知道进程挂起会发生什么。 - R.C
2
如果进程在超时期限内正常退出,ExitCode 将返回一个值。 如果进程挂起,则根本不会退出,并且对正在运行的进程调用 ExitCode 将导致引发 InvalidOperationException。 您还可以使用 Process.Exited 事件和 Process.Kill 方法来管理进程生命周期。 - SWeko

2

以下是一段代码片段,希望对您有所帮助。

http://ss64.com/nt/cmd.html 提供 cmd.exe 的帮助信息。

private int CallShell(string exeCommand, string Parameters)
        {
            //http://ss64.com/nt/cmd.html
            /*
            This function will actually take the shell string and envoke the appropriate process
             passing it the arguments to do the work
            */

            // Initialize the process and its StartInfo properties.
            System.Diagnostics.Process ProcessEXE = new System.Diagnostics.Process();

            logger.DebugFormat("About to Start Process - {0} {1}",exeCommand, Parameters);
            try
            {

                ProcessEXE.StartInfo.FileName = exeCommand;


                // Set UseShellExecute to false for redirection.
                //  false if the process should be created directly from the executable file
                ProcessEXE.StartInfo.UseShellExecute = false;
                ProcessEXE.StartInfo.WorkingDirectory = System.Environment.CurrentDirectory;

                //EnableRaisingEvents property indicates whether the component should be notified when the operating system has shut down a process

                ProcessEXE.StartInfo.Arguments = Parameters;

                ProcessEXE.StartInfo.RedirectStandardOutput = true;
                ProcessEXE.StartInfo.RedirectStandardError = true;
                ProcessEXE.EnableRaisingEvents = true;
                ProcessEXE.StartInfo.CreateNoWindow = true;

                ProcessEXE.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(ProcessEXE_OutputDataReceived);
                ProcessEXE.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(ProcessEXE_OutputDataReceived);

                logger.DebugFormat("Process Started.");
                ProcessEXE.Start();


                // Start the asynchronous read of the sort output stream.
                ProcessEXE.BeginErrorReadLine();
                ProcessEXE.BeginOutputReadLine();

                //The WaitForExit overload is used to make the current thread wait until the associated process terminates
                logger.DebugFormat("Process Waiting for exit.");
                ProcessEXE.WaitForExit();

                if (ProcessEXE.ExitCode == 0)
                {
                    logger.Debug(string.Format("Shell Process exited with exit code {0}", ProcessEXE.ExitCode));
                }
                else
                {
                // throw error here if required - check the return error code
                    logger.Warn(string.Format("Shell Process exited with exit code {0}", ProcessEXE.ExitCode));
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Method:{0}", ex.TargetSite), ex);
            }

            return ProcessEXE.ExitCode;
        }


void ProcessEXE_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            try
            {
                StringBuilder sb = new StringBuilder(string.Empty);
                if (e == nullreturn;

                if (e.Data == null)
                {
                    //No processing
                }
                else
                {
                   // your logic to detect error msg out from output - if at all required
                }

                if (sb.ToString().ToUpper().IndexOf("ERROR") > 0)
                {
                    string smessage = "Error text found in  output.";

                // do your error response action here .

                }
            }
            catch (Exception exp)
            {
                logger.ErrorFormat("Error in ProcessEXE_OutputDataReceived Message:{0}", exp.Message);
                logger.ErrorFormat("Error in ProcessEXE_OutputDataReceived Data Received:{0}", e.Data);

            // either throw error msg or kill the process 
            }
            finally
            {
                // Not throwing the exception
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接