'The Console application has exited with code 0 (0x0) although unhandled exception occured

I'm writing very simple code of .Net Framework (4.7) Console Application and intentionally throw unhanded exception. But still the program exit with code 0 (0x0), which supposed to indicate successful accomplishment.

According to Microsoft documentation here The default value is 0 (zero), which indicates that the process completed successfully.

My Q is: I`m expecting any exit code but no 0. Can someone explain me what I'm missing here?

My code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {                    
            throw new Exception("Throw an exception");

            Console.WriteLine("Finishing program");
            Console.ReadLine();
        }
    }
}

The output window (Debug) message:

An unhandled exception of type 'System.Exception' occurred in ConsoleApp2.exe

Throw an exception

The program '[7480] ConsoleApp2.exe' has exited with code 0 (0x0).

Thanks a lot



Solution 1:[1]

This is happening due to... (tadaaa...)

A bug in the visual studio debugger!

The debugger reports that the exit code is zero, but the debugger is lying to you and the exit code is in fact non-zero.

The bug is discussed here: https://github.com/dotnet/runtime/issues/35599#issuecomment-621954472

I quote:

The Visual Studio debugger has a quirk that it reports exit code of programs that terminated due to unhandled exceptions as 0 on Windows, but that only happens when you run the program from VS debugger. It does not happen when you run the program from the command line.

(Note how they are calling it a quirk instead of a bug; the hubris of this company is mind-boggling.)

Try running your program from a batch file and display %errorlevel% to see the real exit code.

Wait, it gets better!

If you use a batch file to see the exit code, you might be surprised to discover that even though the exit code is not zero as the debugger was suggesting, it still is not the exit code you chose; it is -532462766.

That's right, the exit code is -532462766.

Not 0, not 42, not -532462765, but exactly -532462766.

WTF, right?

In 32-bit hex, this number is 0xE0434352, which is a nameless, largely undocumented, blanket HRESULT that basically stands for "error due to some unspecified application-specific reasons, we are not telling you exactly what." In this case, the application-specific reason is that an unhandled DotNet exception caused the process to crash. Rumor has it that this HRESULT is known as "EXCEPTION_COMPLUS" or "CLR_EXCEPTION_V4", although good luck finding a shred of documentation for that. (Also, I could claim that the last 3 hex digits spell "CCR", which constitutes a reference to a well known rock band of the 70ies, good luck refuting my claim!)

Wait, it gets even better!

At this point you might be tempted to try various ways of coercing windows to report an exit code of your own choice instead of the nonsensical -532462766 exit code. You might try:

  • catching the exception and setting ExitCode before rethrowing it;
  • catching the exception and invoking Environment.Exit() passing your own exit code;
  • registering an AppDomain unhandled exception handler and setting ExitCode in there;
  • registering an AppDomain unhandled exception handler and invoking Environment.Exit() with your own exit code from within the handler;

etc.

It will all be a waste of time. None of it will work. Microsoft has gone to great lengths to make damn sure that in the event of an unhandled exception, a DotNet process will terminate with exit code -532462766 and nothing but exit code -532462766.

-532462766 should be enough for everyone.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1