none
Get %errorlevel% from batch file

    Question

  • How to get the error level from batch file
    Process . Exitcode is always returning 0.

    Can anyone help?
    Thursday, January 28, 2010 2:08 PM

Answers

  • Could you describe your problem more clearly?

    Within a batch file, %errorlevel% normally contains the error code from the last command run. In the case your batch ends with a CLS command (typically added to ensure the command interpreter's window gets closed) or with an ECHO command to send some final message to the console, the command will very likely succeed (is there any way to make such commands crash?); so the system would set errorlevel to zero accordingly.

    If you want to retrieve some value produced within the batch (such as a command's error code), your best bet is to send it to some output channel and have a stream to catch that channel from your Process instance (I can get into deeper detail about this if you can confirm this is what you need).

    Also, keep in mind that normally running a batch means something like "invoke CMD.EXE passing some flags and the batch's filename as the arguments": since CMD.EXE (the command line interpreter) will likely succeed (even if its success is just complaining about some issue with the batch file), it will return zero as its error code. This may be interfering with how Exitcode is retrieved.

    With so few details, that's all the advise I can give.

    Hope this helps.

    Regards,
    Herenvardo
    Thursday, January 28, 2010 4:39 PM
  • Honestly, if running a valid batch file through the Process class yielded a non-zero ExitCode, then I'd begin to worry.

    You know that when you try to start a .doc file, for example, Windows will run MS Word (or whatever program you have installed to handle .doc files) and pass the filename to the program, assuming the program will do the rest. If you take a look on Windows task manager, you'll see that the process running from that action is winword.exe, not the .doc file.
    Batches ain't different: just like .doc's are passed to Word, batches are passed roughly the same way to the command line interpreter. So your process isn't really the batch file, but the CMD.EXE that's invoked to interpret your batch file. As long as your batch file has reasonable contents, CMD will succeed at parsing and processing it (if one or more of the commands on the batch fail that's a separate story), so CMD's exit code should be 0 to represent such success.

    In other words, the fact that CMD stays between you and the batch file means that you get CMD's exit code instead of the batch's code. Which in turn means that your need doesn't have an easy solution. So we have to get a bit more creative and look for the possible non-easy solutions. Here are some possibilities:

    1. Have you tried reading Environment.GetEnvironmentVariable("errorlevel")? It should contain the last exit code, but I've noticed that CMD doesn't always update it upon exiting with its own code.
    2. If neither your batch nor the commands it invokes is using the stderr output channel, your best bet is to add a command on the batch to send the %errorlevel% you want to capture there (something like "ECHO %errorlevel% 2<&1" should do, if my memory can be trusted), then on your Process add a stream to read the process' err output and use the number you'll eventually get from there.
    3. Beyond the channels #0 (stdin), 1 (stdout), and 2 (stderr), Windows supports "custom" channels numbered 3 to 9. In principle, you could send the errorlevel value to one of these channels to avoid interfering with "normal" stdout and stderr output, but I don't know for sure if the Process class has any means to recover data from those channels.
    4. The heaviest approach is to implement your own batch interpreter. While this is a tedious task, it's not as complex as it may seem. You simply read the batch, break it into lines, and then run it line by line. For "built-in" commands, you'd have to implement them through .Net (for example, to run a line like "CD whatever" you'd use something close to Environment.CurrentDirectory = "result of resolving 'whatever' to an absolute path";). For other commands (those that are implemented with a .com or .exe file) you'd use Process to run them. Add in a bit of logics to deal with redirections and pipes (<, >, | operators and their friends), and finally add some code to track the ExitCode of each process. After that, you may use the codes in whatever way you need.
    These are the possible approaches that come up to my mind; maybe there are other solutions.

    Hope this helps.

    Regards,
    Herenvardo
    • Marked as answer by Jing0Moderator Monday, February 08, 2010 2:59 AM
    Saturday, January 30, 2010 12:18 PM
  • ExitCode works just fine. Below is an example that demonstrates it working. It runs the 'ping' command with no arguments. This causes Ping to report its syntax and exit with an exit code of 1.

    The process in you are running may not return an error code. This is more common than in the past. I think the current generation of programmers are ignorant of its existance. Probably in part because Windows application frameworks (especially GUI ones) hide the exit code from the programmer.

    using System;
    using System.Diagnostics;
    
    class Program
    {
        static void Main(string[] args)
        {
            Process process = new Process { StartInfo = new ProcessStartInfo("ping") };
            process.Start();
            process.WaitForExit();
            Console.WriteLine("Exit Code: {0}", process.ExitCode);
            Console.ReadKey();
        }
    }
    
    • Marked as answer by Jing0Moderator Monday, February 08, 2010 2:59 AM
    Saturday, January 30, 2010 2:24 PM

All replies

  • Could you describe your problem more clearly?

    Within a batch file, %errorlevel% normally contains the error code from the last command run. In the case your batch ends with a CLS command (typically added to ensure the command interpreter's window gets closed) or with an ECHO command to send some final message to the console, the command will very likely succeed (is there any way to make such commands crash?); so the system would set errorlevel to zero accordingly.

    If you want to retrieve some value produced within the batch (such as a command's error code), your best bet is to send it to some output channel and have a stream to catch that channel from your Process instance (I can get into deeper detail about this if you can confirm this is what you need).

    Also, keep in mind that normally running a batch means something like "invoke CMD.EXE passing some flags and the batch's filename as the arguments": since CMD.EXE (the command line interpreter) will likely succeed (even if its success is just complaining about some issue with the batch file), it will return zero as its error code. This may be interfering with how Exitcode is retrieved.

    With so few details, that's all the advise I can give.

    Hope this helps.

    Regards,
    Herenvardo
    Thursday, January 28, 2010 4:39 PM
  • Thanks Heren,

    I need to run batch files from windows application. I am using Process class and Exitcode for capturing %ErrorLevel%.

    But the problem is Exitcode of process object is always 0 and when I looked into the batch file log errorlevel is 2.

    I ned to pass few args to batch file and capture the result i.e %Errorlevel%.
    So, can u help me in this.

     

    Saturday, January 30, 2010 2:13 AM
  • Honestly, if running a valid batch file through the Process class yielded a non-zero ExitCode, then I'd begin to worry.

    You know that when you try to start a .doc file, for example, Windows will run MS Word (or whatever program you have installed to handle .doc files) and pass the filename to the program, assuming the program will do the rest. If you take a look on Windows task manager, you'll see that the process running from that action is winword.exe, not the .doc file.
    Batches ain't different: just like .doc's are passed to Word, batches are passed roughly the same way to the command line interpreter. So your process isn't really the batch file, but the CMD.EXE that's invoked to interpret your batch file. As long as your batch file has reasonable contents, CMD will succeed at parsing and processing it (if one or more of the commands on the batch fail that's a separate story), so CMD's exit code should be 0 to represent such success.

    In other words, the fact that CMD stays between you and the batch file means that you get CMD's exit code instead of the batch's code. Which in turn means that your need doesn't have an easy solution. So we have to get a bit more creative and look for the possible non-easy solutions. Here are some possibilities:

    1. Have you tried reading Environment.GetEnvironmentVariable("errorlevel")? It should contain the last exit code, but I've noticed that CMD doesn't always update it upon exiting with its own code.
    2. If neither your batch nor the commands it invokes is using the stderr output channel, your best bet is to add a command on the batch to send the %errorlevel% you want to capture there (something like "ECHO %errorlevel% 2<&1" should do, if my memory can be trusted), then on your Process add a stream to read the process' err output and use the number you'll eventually get from there.
    3. Beyond the channels #0 (stdin), 1 (stdout), and 2 (stderr), Windows supports "custom" channels numbered 3 to 9. In principle, you could send the errorlevel value to one of these channels to avoid interfering with "normal" stdout and stderr output, but I don't know for sure if the Process class has any means to recover data from those channels.
    4. The heaviest approach is to implement your own batch interpreter. While this is a tedious task, it's not as complex as it may seem. You simply read the batch, break it into lines, and then run it line by line. For "built-in" commands, you'd have to implement them through .Net (for example, to run a line like "CD whatever" you'd use something close to Environment.CurrentDirectory = "result of resolving 'whatever' to an absolute path";). For other commands (those that are implemented with a .com or .exe file) you'd use Process to run them. Add in a bit of logics to deal with redirections and pipes (<, >, | operators and their friends), and finally add some code to track the ExitCode of each process. After that, you may use the codes in whatever way you need.
    These are the possible approaches that come up to my mind; maybe there are other solutions.

    Hope this helps.

    Regards,
    Herenvardo
    Saturday, January 30, 2010 12:07 PM
  • Honestly, if running a valid batch file through the Process class yielded a non-zero ExitCode, then I'd begin to worry.

    You know that when you try to start a .doc file, for example, Windows will run MS Word (or whatever program you have installed to handle .doc files) and pass the filename to the program, assuming the program will do the rest. If you take a look on Windows task manager, you'll see that the process running from that action is winword.exe, not the .doc file.
    Batches ain't different: just like .doc's are passed to Word, batches are passed roughly the same way to the command line interpreter. So your process isn't really the batch file, but the CMD.EXE that's invoked to interpret your batch file. As long as your batch file has reasonable contents, CMD will succeed at parsing and processing it (if one or more of the commands on the batch fail that's a separate story), so CMD's exit code should be 0 to represent such success.

    In other words, the fact that CMD stays between you and the batch file means that you get CMD's exit code instead of the batch's code. Which in turn means that your need doesn't have an easy solution. So we have to get a bit more creative and look for the possible non-easy solutions. Here are some possibilities:

    1. Have you tried reading Environment.GetEnvironmentVariable("errorlevel")? It should contain the last exit code, but I've noticed that CMD doesn't always update it upon exiting with its own code.
    2. If neither your batch nor the commands it invokes is using the stderr output channel, your best bet is to add a command on the batch to send the %errorlevel% you want to capture there (something like "ECHO %errorlevel% 2<&1" should do, if my memory can be trusted), then on your Process add a stream to read the process' err output and use the number you'll eventually get from there.
    3. Beyond the channels #0 (stdin), 1 (stdout), and 2 (stderr), Windows supports "custom" channels numbered 3 to 9. In principle, you could send the errorlevel value to one of these channels to avoid interfering with "normal" stdout and stderr output, but I don't know for sure if the Process class has any means to recover data from those channels.
    4. The heaviest approach is to implement your own batch interpreter. While this is a tedious task, it's not as complex as it may seem. You simply read the batch, break it into lines, and then run it line by line. For "built-in" commands, you'd have to implement them through .Net (for example, to run a line like "CD whatever" you'd use something close to Environment.CurrentDirectory = "result of resolving 'whatever' to an absolute path";). For other commands (those that are implemented with a .com or .exe file) you'd use Process to run them. Add in a bit of logics to deal with redirections and pipes (<, >, | operators and their friends), and finally add some code to track the ExitCode of each process. After that, you may use the codes in whatever way you need.
    These are the possible approaches that come up to my mind; maybe there are other solutions.

    Hope this helps.

    Regards,
    Herenvardo
    • Marked as answer by Jing0Moderator Monday, February 08, 2010 2:59 AM
    Saturday, January 30, 2010 12:18 PM
  • ExitCode works just fine. Below is an example that demonstrates it working. It runs the 'ping' command with no arguments. This causes Ping to report its syntax and exit with an exit code of 1.

    The process in you are running may not return an error code. This is more common than in the past. I think the current generation of programmers are ignorant of its existance. Probably in part because Windows application frameworks (especially GUI ones) hide the exit code from the programmer.

    using System;
    using System.Diagnostics;
    
    class Program
    {
        static void Main(string[] args)
        {
            Process process = new Process { StartInfo = new ProcessStartInfo("ping") };
            process.Start();
            process.WaitForExit();
            Console.WriteLine("Exit Code: {0}", process.ExitCode);
            Console.ReadKey();
        }
    }
    
    • Marked as answer by Jing0Moderator Monday, February 08, 2010 2:59 AM
    Saturday, January 30, 2010 2:24 PM
  • Hi,

     

    How is this problem now?

     

    Please remember to click “Mark as Answer” on the post that helps you.This can be beneficial to other community members reading the thread.

     

    If there is anything unclear, please feel free to tell us.

     

    Best regards,

    Ling Wang


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    Thursday, February 04, 2010 12:06 PM
  • Thanks Heren,

           Thanks for your support.
           Batch file are done by 3rd party.
           They have modified the batch files as exit 2 instead of exit /b 2.Now I could able to retrieve through Exit code.
           And output message are retrieved through output channel.


    Goutham J
    Wednesday, March 03, 2010 3:13 AM