3

I have a WinForm project that I want to be usable as a console app if certain arguments are passed into it. Using some tips I read from here, I used the following code to make this work.

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);

...

if (!AttachConsole(-1))
{
   AllocConsole();
}

This works, but there is one annoying side effect - all the output seems to be generated from a background thread. When I run the program from a command prompt, the output displays the next prompt before displaying the output.

I set the project properties' Output Type to Console Application and it fixed this problem, but now there is always a console window displayed - even when it is run in 'WinForm mode'.

Is there a way to get the best of both worlds where the console behaves like the program is the current process and the console window is not displayed when the program displays the WinForm?

UPDATE: My apologies for not clarifying this. I am toggling between console and WinForm mode in Program.cs like this:

// nowin is a bool that is set based on a parameter
if (nowin)
{
    if (!AttachConsole(-1))
    {
        AllocConsole();
    }
    //... Console mode code here...
}
else
{
    // run in window
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1(argDict));
}
  • What you have discovered isn't a "side-effect" its now WinForm applications work. It would be fair easier if you had seperate programs. Just design your application so this is possible. – Security Hound Oct 12 '11 at 16:44
  • 1
    possible duplicate of [Difference between console and winforms applications when running from cmd](http://stackoverflow.com/questions/7613880/difference-between-console-and-winforms-applications-when-running-from-cmd) – Hans Passant Oct 12 '11 at 16:53

4 Answers4

6

Maybe I've been doing it wrong but I've always done hybrids like this:

[STAThread]
public static int Main(string[] args)
{
   if (args.Length > 0)
   {
      // run console code here
   }
   else
   {
      // start up the win form app
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new MainForm());
   }

   return 0;
}
Russell McClure
  • 4,821
  • 1
  • 22
  • 22
2

Instead of this iffy method, you can accomplish this by just creating a winforms application and not displaying the main form if a certain argument is passed on the command line.

Since a console application doesn't need a message loop, you don't call Application.Run() when called in console mode.

So your Main() would be something like:

    static void Main(params string[] args)
    {
        if (args.Length > 0 && args[0] == "consolemode")
        {
            // do stuff 
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }

I haven't tried this but I think it would work.

Igby Largeman
  • 16,495
  • 3
  • 60
  • 86
1

It looks like there is no way around it: 1) If I want the output in console mode to behave like a dedicated console app, the console window must always be there. 2) If I want to hide the console when I run it in windowed mode, I will lose the blocking prints.

0

The above will work, but it won't allow you to write to the console which is maddening if you're trying to debug exceptions. To write to the console from a Win Forms app, you need to apply the code described here: http://www.codeissue.com/issues/i24e1ef8e5a93b4/run-windows-form-application-as-console-app-c.

Andy
  • 2,709
  • 5
  • 37
  • 64