'C# Console Application: Is there a way to detect whether the exe was run from a command line or not?

If I run my Program.exe from an existing command line window, then when it finishes and exits, the Console Output is still there and viewable.

If I just double click my Program.exe, then it'll open a new command line window, for Console Output ... but when my exe finishes, that window will close, taking the Outputs with it.

In the latter case, to prevent loss of output logs, I might want to have the final 2 lines of my Main() be Console.WriteLine("Press any key to exit"); Console.ReadKey();

But if I do that in the former case then it's mildly annoying.

Is there any way to detect the difference between those 2 scenarios, so that I can do that "wait for the user to say I can close" conditionally ... only if necessary?



Solution 1:[1]

If you want to check if your app is started from the command line in .NET, you can use Console.GetCursorPosition(). The reason that this works is that when you start it from the command line, the cursor moves away from the initial point ((0, 0)) because you typed something in the terminal (the name of the app). You can do this with an equality check:

// .NET 6
class Program
{
    public static void Main(string[] args)
    {
        if (Console.GetCursorPosition() == (0, 0))
        {
            //something GUI
        }
        else
        {
            //something not GUI
        }
    }
}

Note: You must set the output type to Console Application as other output types will make Console.GetCursorPosition() throw an exception.

Solution 2:[2]

For the cases of running a console app from a command line and running it from Visual Studio, Process.GetCurrentProcess().MainWindowTitle is empty. In these cases, you do NOT need the extra Console.ReadLine().

When you run it by double clicking it in Windows Explorer, the window title is the path of the exe. In this case, you DO need the extra Console.ReadLine().

So a somewhat hacky approach (which I've only tested for the three cases above!) could be to add this to the end of Main():

if (!string.IsNullOrEmpty(Process.GetCurrentProcess().MainWindowTitle))
    Console.ReadLine();

I wouldn't use this in production code, but it could be useful as a quick hack for test utilities etc.

Solution 3:[3]

Before .Net5:

if (Console.Title == System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)
{
    //Title in Explorer (and VS) contains path + filename
    Console.WriteLine("Executed in Explorer");
    Console.ReadLine();
}

if (Console.Title.Contains("Command Prompt"))
    Console.WriteLine("Executed in a 'Command Prompt'");

if (Console.Title.Contains("PowerShell"))
    Console.WriteLine("Executed in PowerShell");

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
Solution 2 Matthew Watson
Solution 3 Jonas Grundén