Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# console application: Main method return value VS Application.ExitCode

I am writing a console program for windows task scheduler to run. My Main() method has a return type of int and I return different numbers when exiting to indicate the result of execution, which I can access in a .BAT script as %errorlevel%.

However when debugging in VS2015, I do a

return 255;

and I always get from the Output window of VS2015:

The program '[43560] Foo.vshost.exe' has exited with code 0 (0x0).

Now if I want the Output window to display the exit code of my program I have to do a Application.Exit(255) for it to show

The program '[24400] Foo.vshost.exe' has exited with code 255 (0xff).

What's strange is the %errorlevel% is correctly set to 255 if I run the program in CMD.exe with either the return statement or Environment.Exit().

So my question is

  1. Is the return value of Main() somewhat different to Environment.ExitCode?

  2. What is the way to easily find out the return value of Main() method in VS2015?

  3. When exiting a console program, is Environment.Exit() preferred than a simple return statement? Because a return statement is more concise to my taste.

Could somebody tell me the story behind this? Thanks.

like image 924
Lionet Chen Avatar asked Jun 10 '16 04:06

Lionet Chen


1 Answers

Is the return value of Main() somewhat different to Environment.ExitCode?

Nope, they are the same, and go to the same place. You can see this by experimenting with a console application that just either returns -1 or sets Environment.ExitCode to -1. You'll see that whichever method you use works and sets %ERRORLEVEL% correctly.

What is the way to easily find out the return value of Main() method in VS2015?

First, a quick aside about what appears to be happening. Here's the stack trace for a console application created using the default project settings:

TestApp.exe!TestApp.Program.Main(string[] args)
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args)
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()

Notice that the VS host process is there. With the VS hosting process disabled the stack trace (with the same options) looks like this:

TestApp.exe!TestApp.Program.Main(string[] args)

If you look at the definition of ThreadHelper.ThreadStart in the reference source you'll see it defined as:

internal void ThreadStart(object obj)

It seems that either this void return is being used as the process return value, or one of the other methods above it is consuming the return value and swallowing it.

If you change the project configuration and disable the hosting process then you will get output like:

The program '[7992] TestApp.exe' has exited with code -1 (0xffffffff).

As you expect. To disable the hosting process, go to the project properties, and on the debug tab, uncheck the "Enable the Visual Studio hosting process"

When exiting a console program, is Environment.Exit() preferred than a simple return statement? Because a return statement is more concise to my taste.

Whichever you prefer. As pointed out by Jeppe Stig in a comment, for more information about the differences, see the documentation for Environment.Exit

like image 153
theB Avatar answered Dec 10 '22 19:12

theB