5

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"

5 Answers 5

6

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.

Sign up to request clarification or add additional context in comments.

10 Comments

@Andreas Paulsson, I need to use batchfile as per my requirement. How to make sure that the batch script sets the exitcode properly ?
@Anuya: Add a row that says "if "%ERRORLEVEL%" == "1" exit /B 1" at the end of your batch script.
@Andreas Paulsson, Pls see the update for my srcipt in batch file. Its not giving me any notification. Am i doing something wrong ?
@Anuya: remove outer double quotes. As for creating the string i C#, use string mystring = @"if ""%ERRORLEVEL%"" == ""1"" exit /B 1";
@Andreas Paulsson, Yeah that was a mistake and i corrected it now. But still not getting any errors. Is that i have to obtain the ErrorLevel from c# after executing the batch file ?
|
2

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.

Comments

2

Use ExitCode like follows:

System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = @"usbformat.bat";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true; // change to false to show the cmd window
proc.Start();

proc.WaitForExit();

if (proc.ExitCode != 0)
   {
       return false;
   }
   else
   {
       return true;
   }

1 Comment

Works fine for me
0
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(filename);
                    psi.RedirectStandardOutput = true;
                    psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    psi.UseShellExecute = false;
                    System.Diagnostics.Process listFiles;
                    listFiles = System.Diagnostics.Process.Start(psi);
                    System.IO.StreamReader myOutput = listFiles.StandardOutput;
                    listFiles.WaitForExit(2000);
                    if (listFiles.HasExited)
                    {
                        string output = myOutput.ReadToEnd();
                        MessageBox.Show(output);
                    }

Comments

-1

you can get it from procinfo.ExitCode

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.