views:

271

answers:

4

I am looking to have one of my Windows Forms applications be run programmatically—from the command line. In preparation, I have separated the logic in its own class from the Form. Now I am stuck trying to get the application to switch back and forth based on the presence of command line arguments.

Here is the code for the main class:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        string[] args = Environment.GetCommandLineArgs();
        if (args.Length > 1) // gets passed its path, by default
        {
            CommandLineWork(args);
            return;
        }         

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    private static void CommandLineWork(string[] args)
    {
        Console.WriteLine("It works!");
        Console.ReadLine();
    }

where Form1 is my form and the It works! string is just a placeholder for the actual logic.

Right now, when running this from within Visual Studio (with command line arguments), the phrase It works! is printed to the Output. However, when running the /bin/Debug/Program.exe file (or /Release for that matter) the application crashes.

Am I going about this the right way? Would it make more sense (i.e. take less developer time) to have my logic class be a DLL that gets loaded by two separate applications? Or is there something entirely different that I'm not aware of?

Thanks in advance!

+1  A: 

Yes it would be better to make two frontend .exes (one for the command line and one for windowing).

The main reason is that you have to specify the output type for your project (either command line or Windows application and you can't select both.

So you would have to always use the Windows application output type (which comes at an overhead for the Windows messaging system and doesn't give you "real" command line).

Foxfire
A: 

Not sure if it makes a difference but instead of

static void Main()
{
        string[] args = Environment.GetCommandLineArgs();

you can instead put

static void Main(string[] args)
{
Kyra
+4  A: 

You'll need to P/Invoke AllocConsole() if you detect a command line argument. Check my answer in this thread for the required code. A C# sample is further down the page. Repeated here because I don't trust that crummy forum site:

using System;
using System.Windows.Forms;

namespace WindowsApplication1 {
  static class Program {
    [STAThread]
    static void Main(string[] args) {
      if (args.Length > 0) {
        // Command line given, display console
        AllocConsole();
        ConsoleMain(args);
      }
      else {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
      }
    }
    private static void ConsoleMain(string[] args) {
      Console.WriteLine("Command line = {0}", Environment.CommandLine);
      for (int ix = 0; ix < args.Length; ++ix)
        Console.WriteLine("Argument{0} = {1}", ix + 1, args[ix]);
      Console.ReadLine();
    }

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static extern bool AllocConsole();
  }
}
Hans Passant
You can also use `FreeConsole`: http://stackoverflow.com/questions/1786840/c-is-it-possible-to-have-a-single-application-behave-as-console-or-windows-appl/1787008#1787008
adrianbanks
Why not just make it a console app in the first place and then reference the Forms assembly for the windowing?
Chris Dunaway
@Chris: get a console only on demand, not always. FreeConsole is a *nasty* flash.
Hans Passant
Fantastic! This works perfectly. Thank you!
Aeolien
A: 

Are you actually going to run it as a real console app with asking the user to enter data etc, or are you just going to start it up with some arguments so that it can be run from a batch file or a scheduled task or similar?

If it's a real console app, I'd agree with Foxfire that it's probably worth having 2 exe files, but otherwise I'd keep it as one exe. I've done plenty of those without any issues.

What's the exact exception that's occuring though?

ho1