+3  A: 

Just build it as a Windows Forms app, but don't give it a GUI. Unfortunately then you won't get any console output when it's run from the command line either... is that a problem?

Jon Skeet
Hmm, I know how to work around *that*. Thanks!
Cheeso
Thinking about this a little more, I don't think this will work. I know how to make an EXE either a console app or a WinForms app at runtime, using pinvoke on AttachConsole(). But I don't know how to determine when to make it a console app or a Winforms app. I don't know how to detect if it was lauched by a double-click in explorer, or launched from a console window.
Cheeso
Why not use a command line argument to select console display mode? That way when run from Explorer, it won't have one; unless you create a shortcut and add the argument there - allowing you to have both with and without console launches from Explorer.
Clifford
That doesn't quite do it for me. First because I don't want the behavior to be command-line selectable. I want it to be automatic. Second because using the parent's console isn't the same as being a regular console app. See the blog post from Old New Thing http://blogs.msdn.com/oldnewthing/archive/2009/01/01/9259142.aspxfor an explanation of why.
Cheeso
A: 

Would this be more like a Service then?

  • or -

What About a Windows Forms application that doesn't have a visible form? It would still show up in the Task Manager Processes list.

Aaron Hoffman
+2  A: 

See http://stackoverflow.com/questions/510805/can-a-win32-console-application-detect-if-it-has-been-run-from-the-explorer-or-no

Or I think the official way is to check the parent process is cmd.exe or explorer.exe

Martin Beckett
+4  A: 

So, I've written tools with both a GUI and a CLI. The hard part was figuring out which one to open - in our case, though, the CLI version had required parameters, so I just opened the GUI if there weren't any parameters. Then, if they did want a console, call a function that looks something like:

private const int ATTACH_PARENT_PROCESS = -1;
private const int ERROR_INVALID_HANDLE = 6;
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll")]
static extern bool AllocConsole();
[DllImport("kernel32.dll")]
static extern bool FreeConsole();

private static bool StartConsole()
{
  if (!AttachConsole(ATTACH_PARENT_PROCESS)) // try connecting to an existing console  
  {  
      if (Marshal.GetLastWin32Error() == ERROR_INVALID_HANDLE) // we don't have a console yet  
      {  
          if (!AllocConsole()) // couldn't create a new console, either  
              return false;  
      }
      else
          return false; // some other error
  }
  return true;
}

Returns whether the console was created. Don't forget to FreeConsole() when you're done!

In our case, of course, if we don't create a console, we create a GUI. It'd be just as easy to create either a console or no UI, though.

EDIT: That totally didn't answer the question in the edit that wasn't there when I started writing that, of course. Other than that our hack was just checking whether it was called with command-line parameters or not.

neminem
This is helpful - it lets me create a console app or not at runtime. The key thing is, how to determine whether a console is present. I think that is AttachConsole(-1), but even when that returns 0, I don't know how to suppress the console when it is not present. I'll have to try a few things. thanks
Cheeso