从ASP.NET启动外部进程

时间:2009-02-23 19:04:47

标签: c# .net asp.net

我需要从我的Web应用程序启动外部进程。这意味着使用 System.Diagnostics.ProcessStartInfo 来调用并执行控制台应用程序(exe)。但我需要以某种方式 确保在执行期间没有出错 ,并知道应用程序何时完成其工作。

什么是捕获所有可能错误并找出错误的最佳方式?

6 个答案:

答案 0 :(得分:4)

使用Process类并不是那么难。虽然,之前的海报是正确的 - 你需要关注权限。

private string RunProcess(string cmd)
{
  System.Diagnostics.Process p; 
  p= new System.Diagnostics.Process();
  if (cmd== null || cmd=="") {
    return "no command given.";
  }
  string[] args= cmd.Split(new char[]{' '});
  if (args== null || args.Length==0 || args[0].Length==0) {
    return "no command provided.";
  }
  p.StartInfo.FileName= args[0];

  if (args.Length>1) {
    int startPoint= cmd.IndexOf(' ');
    string s= cmd.Substring(startPoint, cmd.Length-startPoint);
    p.StartInfo.Arguments= s; 
  }
  p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
  p.StartInfo.RedirectStandardOutput = true;
  p.StartInfo.UseShellExecute = false;

  p.Start();

  // must have the readToEnd BEFORE the WaitForExit(), to avoid a deadlock condition
  string output= p.StandardOutput.ReadToEnd();
  p.WaitForExit();

  return output; 
}

答案 1 :(得分:2)

我当然希望你能控制外部应用程序的代码,否则你会遇到很多麻烦。最重要的事情是确保该应用程序无法挂起而不能终止。

然后,您可以使用WaitForExit(),ExitCode,StandardError,StandardOut“捕获所有可能的错误并找出它何时完成”

答案 2 :(得分:2)

你最好抓住控制台应用程序的所有输出并将其存储在可以在状态页面上显示的地方,而不是等待应用程序完成。

正如上面其他人所说的那样,否则你会经历痛苦。

答案 3 :(得分:1)

你会遇到这个问题。 ASP.NET网页在严格的安全上下文中运行,甚至可能无法启动外部进程。

另外...... ASP.NET将“随心所欲”回收(停止/重启所有进程)。这意味着任何时候网页都可以中止执行。

您是否考虑过使用作业/任务调度程序? SQL Server附带的版本(非快速版)非常好。

答案 4 :(得分:1)

您无法从外部程序中捕获任何错误。最大限度你可以将它的输出重定向到你自己的流,并希望它会在失败/成功时写出一些东西。您可以使用Process.ExitCode来检查进程退出代码。

您可以使用Process.Exited事件或Process.HasExited属性测试流程是否已完成。

此外,您应该注意,默认情况下,Asp.Net代码在NETWORK SERVICE流程(iis6及更高版本)下运行,因此它具有有限的权限,登录用户将无法看到它的UI。

@rbobby:您可以在Asp.Net代码中启动外部进程,但它将继承Asp.Net代码的安全上下文。

答案 5 :(得分:1)

希望这个答案有所帮助

https://stackoverflow.com/a/14107672/1060656

这是一个代码段,希望这有帮助

对于cmd.exe帮助

http://ss64.com/nt/cmd.html

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 == null) return;

                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
            }
        }