Is it possible to build a Console app that does not display a console Window when double-clicked?
.net, console, console-application, windows
Solution
See Can a Win32 console application detect if it has been run from the explorer or not?
Or I think the official way is to check the parent process is cmd.exe or explorer.exe
Problem
Related: Should I include a command line mode in my applications? How to grab parent process standard output? Can a console application detect if it has been run from Explorer? I want to build a console app, that is normally run from the command line. But, when it is double clicked from within Explorer (as opposed to being run from a cmd.exe prompt) then I'd like the program to NOT display a console window. I want to avoid this: Is it possible? EDIT I guess another way to ask it is, is it possible for a program to know how it was invoked - whether by double-click or by command line ? I'm working in .NET, on Windows. EDIT 2: From this Old New Thing blog post I learned some good stuff. Here's what I know now... In Windows, EXE files are marked as either GUI or non-GUI. With csc.exe, this is selected with `/target:winexe` or `/target:exe`. Before the first instruction in the process executes, the Windows kernel sets up the execution environment. At that moment, if the EXE is marked GUI, the kernel sets the stdin/stdout for the process to NULL, and if non-GUI (command-line) the kernel creates a console and sets the stdin/stdout for the process to that console. When launching the process, if there is no stdin/stdout (== `/target:winexe`), then the call immediately returns. So, launching a gui app from a cmd.exe, you will immediately get your cmd prompt back. If there is a stdin/stdout, and if run from cmd.exe, then the parent cmd.exe waits for process exit. The "immediate return" is important because if you code a GUI app to attach to its parent's console, you will be able to do console.writeline, etc. But the cmd.exe prompt is active. The user can type new commands, start a new process, and so on. In other words, from a winexe, simply attaching to the parent console with `AttachConsole(-1)` will not "turn it into" a console app. At this point I think the only way to allow an app to use the console if it is invoked from cmd.exe, and NOT use it if it is double-clicked, is to define the exe as a regular console exe (`/target:exe`), and hide the window on startup if appropriate. You still get a console window appearing briefly. I still haven't figured how to know whether it was launched from explorer or cmd.exe, but I'm getting closer.. ANSWERS It is not possible to build a console app that does not display a console window. It is possible to build a console app that hides its window very quickly, but not so quickly that it is as if the window never appears. Now, to determine whether a console app was launched from explorer, some have suggested to look at the console it is running in (from mgb's answer, and KB article 99115) : ``` int left = Console.CursorLeft; int top = Console.CursorTop; bool ProcessWasRunFromExplorer = (left==0 && top==0); ``` This tells you if the process was launched in its own console, but not whether it was explorer. A double click in explorer would do this, but also a Start.Process() from within an app would do the same thing. If you want to treat those situations differently, use this to learn the name of the parent process: ``` System.Console.WriteLine("Process id: {0}", Process.GetCurrentProcess().Id); string name = Process.GetCurrentProcess().ProcessName ; System.Console.WriteLine("Process name: {0}", name); PerformanceCounter pc = new PerformanceCounter("Process", "Creating Process Id", name); Process p = Process.GetProcessById((int)pc.RawValue); System.Console.WriteLine("Parent Process id: {0}", p.Id); System.Console.WriteLine("Parent Process name: {0}", p.ProcessName); // p.ProcessName == "cmd" or "Explorer" etc ``` To hide the window quickly after the process is launched, use this: ``` private static readonly int SW_HIDE= 0; [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow); .... { IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle; ShowWindow(myHandle, SW_HIDE); } ``` If you produce a `winexe` (a WinForms app), and optionally attach to the parent console when appropriate with `AttachConsole(-1)`, you do not get the equivalent of a regular console app. For a winexe, the parent process (like cmd.exe) will return to the command prompt immediately after starting a GUI application. In other words, the command prompt is active and ready for input while the just-launched process may be emitting output. This is confusing and is probably useful only for debugging winforms apps. This worked for me.