Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain Exitcode from CMD using c#

Tags:

c#

I am using following code to write the PATH, EXECUTABLE NAME and ARGUMENTS to a batch file and execute it through CMD using c#. The problem is sometimes the application dosent starts up after executing the batch file. And the c# code dosent give me exception or any notification.

For which i want to get the Exitcode from CMD to determine if the commands executed properly. How can i determine Exit code ?

  public void Execute()
{
    try
    {
        string LatestFileName = GetLastWrittenBatchFile();
        if (System.IO.File.Exists(BatchPath + LatestFileName))
        {
            System.Diagnostics.ProcessStartInfo procinfo = new System.Diagnostics.ProcessStartInfo("cmd.exe");
            procinfo.UseShellExecute = false;
            procinfo.RedirectStandardError = true;
            procinfo.RedirectStandardInput = true;
            procinfo.RedirectStandardOutput = true;

            System.Diagnostics.Process process = System.Diagnostics.Process.Start(procinfo); 
            System.IO.StreamReader stream = System.IO.File.OpenText(BatchPath + LatestFileName);
            System.IO.StreamReader sroutput = process.StandardOutput;
            System.IO.StreamWriter srinput = process.StandardInput;


            while (stream.Peek() != -1)
            {
                srinput.WriteLine(stream.ReadLine());
            }

            Log.Flow_writeToLogFile("Executed .Bat file : " + LatestFileName);

            process.WaitForExit(1000);

            if (process.ExitCode != 0)
            {
                int iExitCode = process.ExitCode;
            }
            stream.Close();
            process.Close();
            srinput.Close();
            sroutput.Close(); 
        }
        else
        {
            ExceptionHandler.writeToLogFile("File not found");
        }
    }
    catch (Exception ex)
    {
        ExceptionHandler.writeToLogFile(System.Environment.NewLine + "Target  :  " + ex.TargetSite.ToString() + System.Environment.NewLine + "Message :  " + ex.Message.ToString() + System.Environment.NewLine + "Stack   :  " + ex.StackTrace.ToString());
    }
} 

_________________Update___________________

script inside Batchfile : [Note that Notepads.exe is wrong to get the error ]

START Notepads.EXE

"if "%ERRORLEVEL%" == "1" exit /B 1"

like image 881
Anuya Avatar asked Jan 22 '23 10:01

Anuya


2 Answers

It is much easier to run the process directly instead of using creating a batch file that you later execute since you lose some control since you are using a batch script layer.

Use this code instead:

    /// <summary>
    /// Execute external process.
    /// Block until process has terminated.
    /// Capture output.
    /// </summary>
    /// <param name="binaryFilename"></param>
    /// <param name="arguments"></param>
    /// <param name="currentDirectory"></param>
    /// <param name="priorityClass">Priority of started process.</param>
    /// <returns>stdout output.</returns>
    public static string ExecuteProcess(string binaryFilename, string arguments, string currentDirectory, ProcessPriorityClass priorityClass)
    {
        if (String.IsNullOrEmpty(binaryFilename))
        {
            return "no command given.";
        }

        Process p = new Process();
        p.StartInfo.FileName = binaryFilename;
        p.StartInfo.Arguments = arguments;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.UseShellExecute = false;
        if (!String.IsNullOrEmpty(currentDirectory))
            p.StartInfo.WorkingDirectory = currentDirectory;
        p.StartInfo.CreateNoWindow = false;

        p.Start();
        // Cannot set priority process is started.
        p.PriorityClass = priorityClass;

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

        if (p.ExitCode != 0)
        {
            throw new Exception(String.Format("Process '{0} {1}' ExitCode was {2}",
                                 binaryFilename,
                                 arguments,
                                 p.ExitCode));   
        }
        //string standardError = p.StandardError.ReadToEnd();
        //if (!String.IsNullOrEmpty(standardError))
        //{
        //    throw new Exception(String.Format("Process '{0} {1}' StandardError was {2}",
        //                         binaryFilename,
        //                         arguments,
        //                         standardError));
        //}

        return output;
    }

I use it in a number of projects and it works like a charm.

If you HAVE to go the batch script route, make sure that the batch script set exitcode properly.

like image 57
Andreas Paulsson Avatar answered Feb 03 '23 13:02

Andreas Paulsson


Does the Process.ExitCode property not give you what you want? Obviously you'd need to make sure that the batch file itself exits with the right exit code, mirroring the application it's running.

By the way, you should use using statements to make sure that all the relevant streams are closed in the face of exceptions - and I would suggest the asynchronous ways of reacting to data from the application, rather than synchronous IO. If you do stick to synchronous IO, you should have another thread reading from standard error - otherwise if the process writes a lot of data to standard error, it will block waiting for you to clear the buffer.

like image 43
Jon Skeet Avatar answered Feb 03 '23 14:02

Jon Skeet